Compare commits

..

69 Commits

Author SHA1 Message Date
Anders Fugmann
73052363a6 Kotlin: fix 2.4 registrar build regression
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 14:50:03 +02:00
Anders Fugmann
e5cb6b4496 Kotlin: address reviewer feedback on versioning and registrar wiring
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 14:20:26 +02:00
Anders Fugmann
4723dfc76c Tests: revert unproven Kotlin expectation drift 2026-06-12 13:32:39 +02:00
Anders Fugmann
547c78f8b9 Kotlin: refresh test expectations for 2.4 2026-06-12 11:51:12 +02:00
Anders Fugmann
b9f2afff9a Kotlin: add extractor support for 2.4.0 2026-06-12 11:51:04 +02:00
Tom Hvitved
3da195f50f Merge pull request #21918 from hvitved/rust/expose-resolution
Rust: Add `Impl::getSelf()` and `Impl::getTrait()`
2026-06-03 20:18:05 +02:00
Tom Hvitved
0430c71318 Merge pull request #21922 from hvitved/rust/static-const-resolution
Rust: Path resolution for `static` items
2026-06-03 17:48:21 +02:00
Owen Mansel-Chan
52f2a5825a Merge pull request #21804 from github/copilot/add-tests-for-models
Java: Update CWE-918 model coverage for Apache HttpClient `execute` sinks
2026-06-03 12:55:56 +01:00
Owen Mansel-Chan
d55ff83568 Merge pull request #21269 from owen-mc/go/improve-tests-for-varargs-flow
Go: improve tests for varargs flow
2026-06-03 12:39:46 +01:00
Asger F
7edf0100cc Merge pull request #21924 from asgerf/asgerf/yeast-changes
Yeast: some fixes
2026-06-03 10:32:38 +02:00
Owen Mansel-Chan
167c837088 Merge pull request #21914 from owen-mc/shared/cfg/if-init
Shared CFG: allow init stmts for IfStmt
2026-06-02 22:01:02 +01:00
Tom Hvitved
af45e53e77 Rust: Rename parameter in DB upgrade script 2026-06-02 21:18:53 +02:00
Jeroen Ketema
d11fc3a00e Merge pull request #21932 from jketema/jketema/vue
JS: Add Vue to `file_coverage_languages` and `github_api_languages`
2026-06-02 17:53:25 +02:00
Jeroen Ketema
9d5dfea5c5 JS: Add Vue to file_coverage_languages and github_api_languages 2026-06-02 16:57:51 +02:00
Tom Hvitved
dc0c7d7ec2 Fix commment typos 2026-06-02 14:41:27 +02:00
Owen Mansel-Chan
aaa3b363e1 Merge pull request #21929 from owen-mc/go/no-ret-functions
Go: Recognize more non-returning logging functions
2026-06-02 10:39:28 +01:00
Owen Mansel-Chan
9dbe9adb00 Update tests 2026-06-02 09:34:03 +01:00
Owen Mansel-Chan
be9c785cb2 Fix incorrect QLDoc
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-06-02 09:26:13 +01:00
Tom Hvitved
1fd31d0ddd Rust: Data flow for consts and statics 2026-06-02 09:55:51 +02:00
Tom Hvitved
c4e3720d8a Rust: Run codegen 2026-06-02 09:02:57 +02:00
Tom Hvitved
0547e9c98d Rust: Path resolution for static items 2026-06-02 09:02:56 +02:00
Owen Mansel-Chan
703cea2b65 Model panicking log functions better 2026-06-02 01:32:00 +01:00
Owen Mansel-Chan
e6e8e3d005 Taint doesn't flow through panicking functions 2026-06-02 01:31:44 +01:00
Owen Mansel-Chan
adc9b7714b Accept changed test output 2026-06-02 00:57:06 +01:00
Owen Mansel-Chan
e706c5f444 Improve test for non-returning fns 2026-06-02 00:56:12 +01:00
Owen Mansel-Chan
8a1e6d4f64 Add missing QLDocs 2026-06-02 00:41:48 +01:00
Owen Mansel-Chan
1a747dd8be (Trivial) Fix QLDoc grammar 2026-06-02 00:39:25 +01:00
Owen Mansel-Chan
28bb1a6870 Add change note 2026-06-02 00:16:23 +01:00
Owen Mansel-Chan
45b1253b23 Improve glog and klog tests 2026-06-02 00:16:21 +01:00
Owen Mansel-Chan
c99dab1d71 Improve glog (and klog) modelling 2026-06-02 00:16:19 +01:00
Owen Mansel-Chan
f3e3647209 Improve noretFunctions test 2026-06-02 00:16:17 +01:00
Owen Mansel-Chan
8d099cbe38 Recognize more non-returning logging functions 2026-06-02 00:15:58 +01:00
Tom Hvitved
9618e9b35c Merge pull request #21873 from hvitved/local-name-resolution
Shared: Local name resolution library
2026-06-01 20:51:07 +02:00
Asger F
3f3bed62d3 yeast: type-check for missing required fields
Add FieldCardinality to Schema to track required/multiple per field,
populated from the ast_types.yml suffixes (bare = required single,
? = optional single, + = required multiple, * = optional multiple).

dump_ast_with_type_errors now emits:
  <-- ERROR: missing required field 'name'
for any node in the output AST whose declared schema requires a field
that is absent from the actual node.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 14:18:37 +02:00
Asger F
21f216af8c yeast-macros: omit empty fields produced by .. splice
When a {..expr} splice in an output template is empty (e.g. from an
optional capture that did not match), drop the field entirely rather
than emitting an empty named field. This lets a single rule with
optional captures replace what used to be two near-identical rules.

Also re-renders the corpus to drop the now-suppressed empty fields.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 14:18:37 +02:00
Asger F
1751d70c62 Fix parsing of corpus tests when --- delimiter is missing 2026-06-01 14:18:37 +02:00
Asger F
ac8eb50c26 Yeast: Allow 'r#type' to escape the 'type' keyword in macro 2026-06-01 14:18:37 +02:00
Asger F
1ecdc3614f Yeast: Fix matching against extras like comments 2026-06-01 14:18:37 +02:00
Asger F
e3b3888bee Yeast: Fix handling of captures with multiple results 2026-06-01 14:18:36 +02:00
Asger F
ef9306d82c Yeast: Allow rules that return an empty sequence 2026-06-01 14:18:36 +02:00
Asger F
56822f8ee1 Tree-sitter-extactor: More helpful panic message 2026-06-01 14:04:49 +02:00
Tom Hvitved
62207f152c Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 13:55:22 +02:00
Tom Hvitved
d5f94475b5 Rust: DB upgrade/downgrade scripts 2026-06-01 10:38:10 +02:00
Tom Hvitved
00e95a0757 Rust: Add Impl::getSelf() and Impl::getTrait() 2026-06-01 10:38:09 +02:00
Tom Hvitved
c695c151ea Rust: Rename Impl::getTrait to Impl::getTraitTy 2026-06-01 10:38:07 +02:00
Tom Hvitved
d2f474d998 Address review comments 2026-06-01 08:30:01 +02:00
Owen Mansel-Chan
5e5a0437e1 Shared CFG: allow init stmts for IfStmt 2026-05-30 07:35:29 +01:00
Tom Hvitved
caae5a8bf1 Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-29 14:24:45 +02:00
Tom Hvitved
09371339d7 Ruby: Adopt shared local name resolution library 2026-05-29 09:06:14 +02:00
Owen Mansel-Chan
d95d99848c Build RequestBuilder more realistically 2026-05-28 11:05:40 +01:00
Owen Mansel-Chan
8937e22735 Add summary models for org.apache.http.client.methods.RequestBuilder
Generated by GPT 5.3-codex, verified by me.
2026-05-28 10:56:37 +01:00
Owen Mansel-Chan
37589dd8a0 Improve how org.apache.http.client.HttpClient is created in test 2026-05-28 10:30:43 +01:00
Owen Mansel-Chan
a159dc1c66 Change variable name in test 2026-05-28 10:28:14 +01:00
Tom Hvitved
7718fe40a0 Ruby: Add more variable tests 2026-05-28 10:50:15 +02:00
Tom Hvitved
aeb82858d7 Rust: Run codegen 2026-05-28 10:50:13 +02:00
Tom Hvitved
c08cf81665 Rust: Adopt shared local name resolution library 2026-05-28 10:50:10 +02:00
Tom Hvitved
e06158629e Rust: More local variable tests 2026-05-28 10:50:05 +02:00
Tom Hvitved
3e09961662 Shared: Add local name binding library 2026-05-28 10:50:03 +02:00
Owen Mansel-Chan
dc864762c3 Add change note 2026-05-07 10:23:50 +01:00
Owen Mansel-Chan
dd35bc0722 Update test output 2026-05-07 10:17:47 +01:00
copilot-swe-agent[bot]
043ec857ab Replace fluent SSRF changes with Apache HttpClient execute model tests
Agent-Logs-Url: https://github.com/github/codeql/sessions/3db201db-a1b5-4353-a94a-14a8d156dd3b

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
2026-05-06 20:31:34 +00:00
copilot-swe-agent[bot]
f5b17b0b48 Add SSRF tests and stubs for Apache Http fluent Request models
Agent-Logs-Url: https://github.com/github/codeql/sessions/bd4fa112-dbc3-47e8-9cef-9b1b13c7e549

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
2026-05-06 16:08:02 +00:00
copilot-swe-agent[bot]
26dca558c7 Initial plan 2026-05-06 16:02:08 +00:00
Owen Mansel-Chan
57ce0b3d51 Accept data flow consistency result 2026-02-05 22:28:54 +00:00
Owen Mansel-Chan
408ba2e139 (Misc) Delete spuriously committed binary file 2026-02-04 13:41:14 +00:00
Owen Mansel-Chan
7632bdba88 (Misc) fix variable names 2026-02-04 13:40:52 +00:00
Owen Mansel-Chan
4b830c1864 Test varargs flow with models-as-data 2026-02-04 13:40:33 +00:00
Owen Mansel-Chan
d6c8767647 Test flow out of varargs parameter in function model 2026-02-04 13:40:01 +00:00
Owen Mansel-Chan
ec815397a2 Test flow out of varargs parameter in source function 2026-02-04 13:38:48 +00:00
244 changed files with 21640 additions and 5535 deletions

View File

@@ -248,6 +248,7 @@ use_repo(
"kotlin-compiler-2.2.20-Beta2", "kotlin-compiler-2.2.20-Beta2",
"kotlin-compiler-2.3.0", "kotlin-compiler-2.3.0",
"kotlin-compiler-2.3.20", "kotlin-compiler-2.3.20",
"kotlin-compiler-2.4.0",
"kotlin-compiler-embeddable-1.8.0", "kotlin-compiler-embeddable-1.8.0",
"kotlin-compiler-embeddable-1.9.0-Beta", "kotlin-compiler-embeddable-1.9.0-Beta",
"kotlin-compiler-embeddable-1.9.20-Beta", "kotlin-compiler-embeddable-1.9.20-Beta",
@@ -259,6 +260,7 @@ use_repo(
"kotlin-compiler-embeddable-2.2.20-Beta2", "kotlin-compiler-embeddable-2.2.20-Beta2",
"kotlin-compiler-embeddable-2.3.0", "kotlin-compiler-embeddable-2.3.0",
"kotlin-compiler-embeddable-2.3.20", "kotlin-compiler-embeddable-2.3.20",
"kotlin-compiler-embeddable-2.4.0",
"kotlin-stdlib-1.8.0", "kotlin-stdlib-1.8.0",
"kotlin-stdlib-1.9.0-Beta", "kotlin-stdlib-1.9.0-Beta",
"kotlin-stdlib-1.9.20-Beta", "kotlin-stdlib-1.9.20-Beta",
@@ -270,6 +272,7 @@ use_repo(
"kotlin-stdlib-2.2.20-Beta2", "kotlin-stdlib-2.2.20-Beta2",
"kotlin-stdlib-2.3.0", "kotlin-stdlib-2.3.0",
"kotlin-stdlib-2.3.20", "kotlin-stdlib-2.3.20",
"kotlin-stdlib-2.4.0",
) )
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -21,7 +21,7 @@
Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK), Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [7]_",``.java`` Eclipse compiler for Java (ECJ) [7]_",``.java``
Kotlin,"Kotlin 1.8.0 to 2.3.2\ *x*","kotlinc",``.kt`` Kotlin,"Kotlin 1.8.0 to 2.4.\ *x*","kotlinc",``.kt``
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_" JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_"
Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* More logging functions are now recognized as not returning or panicking.

View File

@@ -413,17 +413,13 @@ private class ExternalLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
} }
} }
/** private class HeuristicLoggerFunction extends Method {
* A call to an interface that looks like a logger. It is common to use a string logFunctionPrefix;
* locally-defined interface for logging to make it easy to changing logging
* library. HeuristicLoggerFunction() {
*/ exists(string tp, string name |
private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode { this.hasQualifiedName(_, tp, name) and
HeuristicLoggerCall() { this.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
exists(Method m, string tp, string logFunctionPrefix, string name |
m = this.getTarget() and
m.hasQualifiedName(_, tp, name) and
m.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
| |
tp.regexpMatch(".*[lL]ogger") and tp.regexpMatch(".*[lL]ogger") and
logFunctionPrefix = logFunctionPrefix =
@@ -435,6 +431,19 @@ private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode
) )
} }
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
override predicate mustPanic() { logFunctionPrefix = "Panic" }
}
/**
* A call to an interface that looks like a logger. It is common to use a
* locally-defined interface for logging to make it easy to change logging
* library.
*/
private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
HeuristicLoggerCall() { this.getTarget() instanceof HeuristicLoggerFunction }
override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() }
} }

View File

@@ -12,17 +12,37 @@ import go
* forks. * forks.
*/ */
module Glog { module Glog {
/** Gets a package name for `glog` or `klog` (which is a fork). */
string packagePath() {
result =
package([
"github.com/golang/glog", "gopkg.in/glog", "k8s.io/klog", "github.com/barakmich/glog"
], "")
}
private class GlogFunction extends Function { private class GlogFunction extends Function {
int firstPrintedArg; int firstPrintedArg;
string format;
string level;
GlogFunction() { GlogFunction() {
exists(string pkg, string fn, string level | exists(string pkg, string context, int nContextArgs, string depth, int nDepthArgs, string fn |
pkg = package(["github.com/golang/glog", "gopkg.in/glog", "k8s.io/klog"], "") and pkg = packagePath() and
level = ["Error", "Exit", "Fatal", "Info", "Warning"] and level = ["Error", "Exit", "Fatal", "Info", "Warning"] and
( (
fn = level + ["", "f", "ln"] and firstPrintedArg = 0 context = "" and nContextArgs = 0
or or
fn = level + "Depth" and firstPrintedArg = 1 context = "Context" and nContextArgs = 1
) and
(
depth = "" and nDepthArgs = 0
or
depth = "Depth" and nDepthArgs = 1
) and
format = ["", "f", "ln"] and
(
fn = level + context + depth + format and
firstPrintedArg = nContextArgs + nDepthArgs
) )
| |
this.hasQualifiedName(pkg, fn) this.hasQualifiedName(pkg, fn)
@@ -35,10 +55,15 @@ module Glog {
* Gets the index of the first argument that may be output, including a format string if one is present. * Gets the index of the first argument that may be output, including a format string if one is present.
*/ */
int getFirstPrintedArg() { result = firstPrintedArg } int getFirstPrintedArg() { result = firstPrintedArg }
/** Holds if this function takes a format string. */
predicate formatter() { format = "f" }
override predicate mayReturnNormally() { level != "Fatal" and level != "Exit" }
} }
private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction { private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction {
StringFormatter() { this.getName().matches("%f") } StringFormatter() { this.formatter() }
override int getFormatStringIndex() { result = super.getFirstPrintedArg() } override int getFormatStringIndex() { result = super.getFirstPrintedArg() }
} }

View File

@@ -28,6 +28,12 @@ module Logrus {
this.(Method).hasQualifiedName(packagePath(), ["Entry", "Logger"], name) this.(Method).hasQualifiedName(packagePath(), ["Entry", "Logger"], name)
) )
} }
override predicate mayReturnNormally() {
not exists(string level, string suffix | level = ["Fatal", "Panic"] |
this.getName() = level + suffix
)
}
} }
private class StringFormatters extends StringOps::Formatting::Range instanceof LogFunction { private class StringFormatters extends StringOps::Formatting::Range instanceof LogFunction {

View File

@@ -47,7 +47,7 @@ module Zap {
} }
/** A Zap logging function which always panics. */ /** A Zap logging function which always panics. */
private class FatalLogMethod extends Method { private class FatalLogMethod extends ZapFunction {
FatalLogMethod() { FatalLogMethod() {
this.hasQualifiedName(packagePath(), "Logger", "Fatal") this.hasQualifiedName(packagePath(), "Logger", "Fatal")
or or
@@ -58,7 +58,7 @@ module Zap {
} }
/** A Zap logging function which always panics. */ /** A Zap logging function which always panics. */
private class MustPanicLogMethod extends Method { private class MustPanicLogMethod extends ZapFunction {
MustPanicLogMethod() { MustPanicLogMethod() {
this.hasQualifiedName(packagePath(), "Logger", "Panic") this.hasQualifiedName(packagePath(), "Logger", "Panic")
or or

View File

@@ -29,18 +29,37 @@ module Log {
} }
private class LogFormatter extends StringOps::Formatting::Range instanceof LogFunction { private class LogFormatter extends StringOps::Formatting::Range instanceof LogFunction {
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf"] } LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf", "Panic", "Panicf", "Panicln"] }
override int getFormatStringIndex() { result = 0 } override int getFormatStringIndex() { result = 0 }
} }
/** A fatal log function, which calls `os.Exit`. */ /** A fatal log function, which calls `os.Exit`. */
private class FatalLogFunction extends Function { private class FatalLogFunction extends Function {
FatalLogFunction() { this.hasQualifiedName("log", ["Fatal", "Fatalf", "Fatalln"]) } FatalLogFunction() {
exists(string fn | fn = ["Fatal", "Fatalf", "Fatalln"] |
this.hasQualifiedName("log", fn)
or
this.(Method).hasQualifiedName("log", "Logger", fn)
)
}
override predicate mayReturnNormally() { none() } override predicate mayReturnNormally() { none() }
} }
/** A log function which must panic. */
private class PanicLogFunction extends Function {
PanicLogFunction() {
exists(string fn | fn = ["Panic", "Panicf", "Panicln"] |
this.hasQualifiedName("log", fn)
or
this.(Method).hasQualifiedName("log", "Logger", fn)
)
}
override predicate mustPanic() { any() }
}
// These models are not implemented using Models-as-Data because they represent reverse flow. // These models are not implemented using Models-as-Data because they represent reverse flow.
private class FunctionModels extends TaintTracking::FunctionModel { private class FunctionModels extends TaintTracking::FunctionModel {
FunctionInput inp; FunctionInput inp;
@@ -63,30 +82,6 @@ module Log {
FunctionOutput outp; FunctionOutput outp;
MethodModels() { MethodModels() {
// signature: func (*Logger) Fatal(v ...interface{})
this.hasQualifiedName("log", "Logger", "Fatal") and
(inp.isParameter(_) and outp.isReceiver())
or
// signature: func (*Logger) Fatalf(format string, v ...interface{})
this.hasQualifiedName("log", "Logger", "Fatalf") and
(inp.isParameter(_) and outp.isReceiver())
or
// signature: func (*Logger) Fatalln(v ...interface{})
this.hasQualifiedName("log", "Logger", "Fatalln") and
(inp.isParameter(_) and outp.isReceiver())
or
// signature: func (*Logger) Panic(v ...interface{})
this.hasQualifiedName("log", "Logger", "Panic") and
(inp.isParameter(_) and outp.isReceiver())
or
// signature: func (*Logger) Panicf(format string, v ...interface{})
this.hasQualifiedName("log", "Logger", "Panicf") and
(inp.isParameter(_) and outp.isReceiver())
or
// signature: func (*Logger) Panicln(v ...interface{})
this.hasQualifiedName("log", "Logger", "Panicln") and
(inp.isParameter(_) and outp.isReceiver())
or
// signature: func (*Logger) Print(v ...interface{}) // signature: func (*Logger) Print(v ...interface{})
this.hasQualifiedName("log", "Logger", "Print") and this.hasQualifiedName("log", "Logger", "Print") and
(inp.isParameter(_) and outp.isReceiver()) (inp.isParameter(_) and outp.isReceiver())

View File

@@ -1,54 +1,181 @@
//go:generate depstubber -vendor github.com/golang/glog "" Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln //go:generate depstubber -vendor github.com/golang/glog Level,Verbose Error,ErrorContext,ErrorContextDepth,ErrorContextDepthf,ErrorContextf,ErrorDepth,ErrorDepthf,Errorf,Errorln,Exit,ExitContext,ExitContextDepth,ExitContextDepthf,ExitContextf,ExitDepth,ExitDepthf,Exitf,Exitln,Fatal,FatalContext,FatalContextDepth,FatalContextDepthf,FatalContextf,FatalDepth,FatalDepthf,Fatalf,Fatalln,Info,InfoContext,InfoContextDepth,InfoContextDepthf,InfoContextf,InfoDepth,InfoDepthf,Infof,Infoln,V,VDepth,Warning,WarningContext,WarningContextDepth,WarningContextDepthf,WarningContextf,WarningDepth,WarningDepthf,Warningf,Warningln
//go:generate depstubber -vendor k8s.io/klog "" Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln //go:generate depstubber -vendor k8s.io/klog Level,Verbose Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,V,Warning,WarningDepth,Warningf,Warningln
package main package main
import ( import (
"context"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/klog" "k8s.io/klog"
) )
func glogTest() { func glogTest(selector int) {
glog.Error(text) // $ logger=text ctx := context.Background()
glog.ErrorDepth(0, text) // $ logger=text
glog.Errorf(fmt, text) // $ logger=fmt logger=text glog.Error(text) // $ logger=text
glog.Errorln(text) // $ logger=text glog.ErrorContext(ctx, text) // $ logger=text
glog.Exit(text) // $ logger=text glog.ErrorContextDepth(ctx, 0, text) // $ logger=text
glog.ExitDepth(0, text) // $ logger=text glog.ErrorContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
glog.Exitf(fmt, text) // $ logger=fmt logger=text glog.ErrorContextf(ctx, fmt, text) // $ logger=fmt logger=text
glog.Exitln(text) // $ logger=text glog.ErrorDepth(0, text) // $ logger=text
glog.Fatal(text) // $ logger=text glog.ErrorDepthf(0, fmt, text) // $ logger=fmt logger=text
glog.FatalDepth(0, text) // $ logger=text glog.Errorf(fmt, text) // $ logger=fmt logger=text
glog.Fatalf(fmt, text) // $ logger=fmt logger=text glog.Errorln(text) // $ logger=text
glog.Fatalln(text) // $ logger=text if selector == 1 {
glog.Info(text) // $ logger=text glog.Exit(text) // $ logger=text
glog.InfoDepth(0, text) // $ logger=text }
glog.Infof(fmt, text) // $ logger=fmt logger=text if selector == 2 {
glog.Infoln(text) // $ logger=text glog.ExitContext(ctx, text) // $ logger=text
glog.Warning(text) // $ logger=text }
glog.WarningDepth(0, text) // $ logger=text if selector == 3 {
glog.Warningf(fmt, text) // $ logger=fmt logger=text glog.ExitContextDepth(ctx, 0, text) // $ logger=text
glog.Warningln(text) // $ logger=text }
if selector == 4 {
glog.ExitContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
}
if selector == 5 {
glog.ExitContextf(ctx, fmt, text) // $ logger=fmt logger=text
}
if selector == 6 {
glog.ExitDepth(0, text) // $ logger=text
}
if selector == 7 {
glog.ExitDepthf(0, fmt, text) // $ logger=fmt logger=text
}
if selector == 8 {
glog.Exitf(fmt, text) // $ logger=fmt logger=text
}
if selector == 9 {
glog.Exitln(text) // $ logger=text
}
if selector == 10 {
glog.Fatal(text) // $ logger=text
}
if selector == 11 {
glog.FatalContext(ctx, text) // $ logger=text
}
if selector == 12 {
glog.FatalContextDepth(ctx, 0, text) // $ logger=text
}
if selector == 13 {
glog.FatalContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
}
if selector == 14 {
glog.FatalContextf(ctx, fmt, text) // $ logger=fmt logger=text
}
if selector == 15 {
glog.FatalDepth(0, text) // $ logger=text
}
if selector == 16 {
glog.FatalDepthf(0, fmt, text) // $ logger=fmt logger=text
}
if selector == 17 {
glog.Fatalf(fmt, text) // $ logger=fmt logger=text
}
if selector == 18 {
glog.Fatalln(text) // $ logger=text
}
glog.Info(text) // $ logger=text
glog.InfoContext(ctx, text) // $ logger=text
glog.InfoContextDepth(ctx, 0, text) // $ logger=text
glog.InfoContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
glog.InfoContextf(ctx, fmt, text) // $ logger=fmt logger=text
glog.InfoDepth(0, text) // $ logger=text
glog.InfoDepthf(0, fmt, text) // $ logger=fmt logger=text
glog.Infof(fmt, text) // $ logger=fmt logger=text
glog.Infoln(text) // $ logger=text
glog.Warning(text) // $ logger=text
glog.WarningContext(ctx, text) // $ logger=text
glog.WarningContextDepth(ctx, 0, text) // $ logger=text
glog.WarningContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
glog.WarningContextf(ctx, fmt, text) // $ logger=fmt logger=text
glog.WarningDepth(0, text) // $ logger=text
glog.WarningDepthf(0, fmt, text) // $ logger=fmt logger=text
glog.Warningf(fmt, text) // $ logger=fmt logger=text
glog.Warningln(text) // $ logger=text
glog.V(0).Info(text) // $ logger=text
glog.V(0).InfoContext(ctx, text) // $ logger=text
glog.V(0).InfoContextDepth(ctx, 0, text) // $ logger=text
glog.V(0).InfoContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
glog.V(0).InfoContextf(ctx, fmt, text) // $ logger=fmt logger=text
glog.V(0).InfoDepth(0, text) // $ logger=text
glog.V(0).InfoDepthf(0, fmt, text) // $ logger=fmt logger=text
glog.V(0).Infof(fmt, text) // $ logger=fmt logger=text
glog.V(0).Infoln(text) // $ logger=text
glog.VDepth(0, 0).Info(text) // $ logger=text
// components corresponding to the format specifier "%T" are not considered vulnerable // components corresponding to the format specifier "%T" are not considered vulnerable
glog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v glog.ErrorContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v glog.ErrorContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v glog.ErrorDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v glog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v if selector == 19 {
glog.ExitContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 20 {
glog.ExitContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 21 {
glog.ExitDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 22 {
glog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 23 {
glog.FatalContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 24 {
glog.FatalContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 25 {
glog.FatalDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
if selector == 26 {
glog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
glog.InfoContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.InfoContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.InfoDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.WarningContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.WarningContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.WarningDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.V(0).InfoContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.V(0).InfoContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.V(0).InfoDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
glog.V(0).Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
klog.Error(text) // $ logger=text klog.Error(text) // $ logger=text
klog.ErrorDepth(0, text) // $ logger=text klog.ErrorDepth(0, text) // $ logger=text
klog.Errorf(fmt, text) // $ logger=fmt logger=text klog.Errorf(fmt, text) // $ logger=fmt logger=text
klog.Errorln(text) // $ logger=text klog.Errorln(text) // $ logger=text
klog.Exit(text) // $ logger=text if selector == 27 {
klog.ExitDepth(0, text) // $ logger=text klog.Exit(text) // $ logger=text
klog.Exitf(fmt, text) // $ logger=fmt logger=text }
klog.Exitln(text) // $ logger=text if selector == 28 {
klog.Fatal(text) // $ logger=text klog.ExitDepth(0, text) // $ logger=text
klog.FatalDepth(0, text) // $ logger=text }
klog.Fatalf(fmt, text) // $ logger=fmt logger=text if selector == 29 {
klog.Fatalln(text) // $ logger=text klog.Exitf(fmt, text) // $ logger=fmt logger=text
}
if selector == 30 {
klog.Exitln(text) // $ logger=text
}
if selector == 31 {
klog.Fatal(text) // $ logger=text
}
if selector == 32 {
klog.FatalDepth(0, text) // $ logger=text
}
if selector == 33 {
klog.Fatalf(fmt, text) // $ logger=fmt logger=text
}
if selector == 34 {
klog.Fatalln(text) // $ logger=text
}
klog.Info(text) // $ logger=text klog.Info(text) // $ logger=text
klog.InfoDepth(0, text) // $ logger=text klog.InfoDepth(0, text) // $ logger=text
klog.Infof(fmt, text) // $ logger=fmt logger=text klog.Infof(fmt, text) // $ logger=fmt logger=text
@@ -57,11 +184,19 @@ func glogTest() {
klog.WarningDepth(0, text) // $ logger=text klog.WarningDepth(0, text) // $ logger=text
klog.Warningf(fmt, text) // $ logger=fmt logger=text klog.Warningf(fmt, text) // $ logger=fmt logger=text
klog.Warningln(text) // $ logger=text klog.Warningln(text) // $ logger=text
klog.V(0).Info(text) // $ logger=text
klog.V(0).Infof(fmt, text) // $ logger=fmt logger=text
klog.V(0).Infoln(text) // $ logger=text
// components corresponding to the format specifier "%T" are not considered vulnerable // components corresponding to the format specifier "%T" are not considered vulnerable
klog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v klog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
klog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v if selector == 35 {
klog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v klog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
klog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v }
klog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v if selector == 36 {
klog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
}
klog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
klog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
klog.V(0).Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
} }

View File

@@ -3,7 +3,7 @@ module codeql-go-tests/concepts/loggercall
go 1.15 go 1.15
require ( require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/glog v1.2.5
github.com/sirupsen/logrus v1.7.0 github.com/sirupsen/logrus v1.7.0
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
) )

View File

@@ -6,5 +6,6 @@ const text = "test"
var v []byte var v []byte
func main() { func main() {
glogTest(len(v))
stdlib() stdlib()
} }

View File

@@ -2,47 +2,125 @@
// This is a simple stub for github.com/golang/glog, strictly for use in testing. // This is a simple stub for github.com/golang/glog, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library. // See the LICENSE file for information about the licensing of the original library.
// Source: github.com/golang/glog (exports: ; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln) // Source: github.com/golang/glog (exports: Level,Verbose; functions: Error,ErrorContext,ErrorContextDepth,ErrorContextDepthf,ErrorContextf,ErrorDepth,ErrorDepthf,Errorf,Errorln,Exit,ExitContext,ExitContextDepth,ExitContextDepthf,ExitContextf,ExitDepth,ExitDepthf,Exitf,Exitln,Fatal,FatalContext,FatalContextDepth,FatalContextDepthf,FatalContextf,FatalDepth,FatalDepthf,Fatalf,Fatalln,Info,InfoContext,InfoContextDepth,InfoContextDepthf,InfoContextf,InfoDepth,InfoDepthf,Infof,Infoln,V,VDepth,Warning,WarningContext,WarningContextDepth,WarningContextDepthf,WarningContextf,WarningDepth,WarningDepthf,Warningf,Warningln)
// Package glog is a stub of github.com/golang/glog, generated by depstubber. // Package glog is a stub of github.com/golang/glog, generated by depstubber.
package glog package glog
import "context"
type Level int32
type Verbose bool
func Error(_ ...interface{}) {} func Error(_ ...interface{}) {}
func ErrorContext(_ context.Context, _ ...interface{}) {}
func ErrorContextDepth(_ context.Context, _ int, _ ...interface{}) {}
func ErrorContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
func ErrorContextf(_ context.Context, _ string, _ ...interface{}) {}
func ErrorDepth(_ int, _ ...interface{}) {} func ErrorDepth(_ int, _ ...interface{}) {}
func ErrorDepthf(_ int, _ string, _ ...interface{}) {}
func Errorf(_ string, _ ...interface{}) {} func Errorf(_ string, _ ...interface{}) {}
func Errorln(_ ...interface{}) {} func Errorln(_ ...interface{}) {}
func Exit(_ ...interface{}) {} func Exit(_ ...interface{}) {}
func ExitContext(_ context.Context, _ ...interface{}) {}
func ExitContextDepth(_ context.Context, _ int, _ ...interface{}) {}
func ExitContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
func ExitContextf(_ context.Context, _ string, _ ...interface{}) {}
func ExitDepth(_ int, _ ...interface{}) {} func ExitDepth(_ int, _ ...interface{}) {}
func ExitDepthf(_ int, _ string, _ ...interface{}) {}
func Exitf(_ string, _ ...interface{}) {} func Exitf(_ string, _ ...interface{}) {}
func Exitln(_ ...interface{}) {} func Exitln(_ ...interface{}) {}
func Fatal(_ ...interface{}) {} func Fatal(_ ...interface{}) {}
func FatalContext(_ context.Context, _ ...interface{}) {}
func FatalContextDepth(_ context.Context, _ int, _ ...interface{}) {}
func FatalContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
func FatalContextf(_ context.Context, _ string, _ ...interface{}) {}
func FatalDepth(_ int, _ ...interface{}) {} func FatalDepth(_ int, _ ...interface{}) {}
func FatalDepthf(_ int, _ string, _ ...interface{}) {}
func Fatalf(_ string, _ ...interface{}) {} func Fatalf(_ string, _ ...interface{}) {}
func Fatalln(_ ...interface{}) {} func Fatalln(_ ...interface{}) {}
func Info(_ ...interface{}) {} func Info(_ ...interface{}) {}
func InfoContext(_ context.Context, _ ...interface{}) {}
func InfoContextDepth(_ context.Context, _ int, _ ...interface{}) {}
func InfoContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
func InfoContextf(_ context.Context, _ string, _ ...interface{}) {}
func InfoDepth(_ int, _ ...interface{}) {} func InfoDepth(_ int, _ ...interface{}) {}
func InfoDepthf(_ int, _ string, _ ...interface{}) {}
func Infof(_ string, _ ...interface{}) {} func Infof(_ string, _ ...interface{}) {}
func Infoln(_ ...interface{}) {} func Infoln(_ ...interface{}) {}
func V(_ Level) Verbose { return false }
func VDepth(_ int, _ Level) Verbose { return false }
func Warning(_ ...interface{}) {} func Warning(_ ...interface{}) {}
func WarningContext(_ context.Context, _ ...interface{}) {}
func WarningContextDepth(_ context.Context, _ int, _ ...interface{}) {}
func WarningContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
func WarningContextf(_ context.Context, _ string, _ ...interface{}) {}
func WarningDepth(_ int, _ ...interface{}) {} func WarningDepth(_ int, _ ...interface{}) {}
func WarningDepthf(_ int, _ string, _ ...interface{}) {}
func Warningf(_ string, _ ...interface{}) {} func Warningf(_ string, _ ...interface{}) {}
func Warningln(_ ...interface{}) {} func Warningln(_ ...interface{}) {}
func (_ Verbose) Info(_ ...interface{}) {}
func (_ Verbose) InfoContext(_ context.Context, _ ...interface{}) {}
func (_ Verbose) InfoContextDepth(_ context.Context, _ int, _ ...interface{}) {}
func (_ Verbose) InfoContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
func (_ Verbose) InfoContextf(_ context.Context, _ string, _ ...interface{}) {}
func (_ Verbose) InfoDepth(_ int, _ ...interface{}) {}
func (_ Verbose) InfoDepthf(_ int, _ string, _ ...interface{}) {}
func (_ Verbose) Infof(_ string, _ ...interface{}) {}
func (_ Verbose) Infoln(_ ...interface{}) {}

View File

@@ -2,11 +2,15 @@
// This is a simple stub for k8s.io/klog, strictly for use in testing. // This is a simple stub for k8s.io/klog, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library. // See the LICENSE file for information about the licensing of the original library.
// Source: k8s.io/klog (exports: ; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln) // Source: k8s.io/klog (exports: Level,Verbose; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,V,Warning,WarningDepth,Warningf,Warningln)
// Package klog is a stub of k8s.io/klog, generated by depstubber. // Package klog is a stub of k8s.io/klog, generated by depstubber.
package klog package klog
type Level int32
type Verbose bool
func Error(_ ...interface{}) {} func Error(_ ...interface{}) {}
func ErrorDepth(_ int, _ ...interface{}) {} func ErrorDepth(_ int, _ ...interface{}) {}
@@ -39,6 +43,8 @@ func Infof(_ string, _ ...interface{}) {}
func Infoln(_ ...interface{}) {} func Infoln(_ ...interface{}) {}
func V(_ Level) Verbose { return false }
func Warning(_ ...interface{}) {} func Warning(_ ...interface{}) {}
func WarningDepth(_ int, _ ...interface{}) {} func WarningDepth(_ int, _ ...interface{}) {}
@@ -46,3 +52,9 @@ func WarningDepth(_ int, _ ...interface{}) {}
func Warningf(_ string, _ ...interface{}) {} func Warningf(_ string, _ ...interface{}) {}
func Warningln(_ ...interface{}) {} func Warningln(_ ...interface{}) {}
func (_ Verbose) Info(_ ...interface{}) {}
func (_ Verbose) Infof(_ string, _ ...interface{}) {}
func (_ Verbose) Infoln(_ ...interface{}) {}

View File

@@ -1,4 +1,4 @@
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b # github.com/golang/glog v1.2.5
## explicit ## explicit
github.com/golang/glog github.com/golang/glog
# github.com/sirupsen/logrus v1.7.0 # github.com/sirupsen/logrus v1.7.0

View File

@@ -1,11 +1,21 @@
| file://:0:0:0:0 | Exit | package os | | file://:0:0:0:0 | Exit | os.Exit |
| file://:0:0:0:0 | Fatal | package log | | file://:0:0:0:0 | Fatal | log.Fatal |
| file://:0:0:0:0 | Fatalf | package log | | file://:0:0:0:0 | Fatal | log.Logger.Fatal |
| file://:0:0:0:0 | Fatalln | package log | | file://:0:0:0:0 | Fatalf | log.Fatalf |
| noretfunctions.go:8:6:8:12 | isNoRet | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Fatalf | log.Logger.Fatalf |
| noretfunctions.go:20:6:20:22 | noRetUsesLogFatal | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Fatalln | log.Fatalln |
| noretfunctions.go:24:6:24:23 | noRetUsesLogFatalf | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Fatalln | log.Logger.Fatalln |
| stmts7.go:10:6:10:15 | canRecover | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Panic | log.Logger.Panic |
| stmts.go:10:6:10:10 | test5 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Panic | log.Panic |
| stmts.go:46:6:46:10 | test6 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Panicf | log.Logger.Panicf |
| stmts.go:112:6:112:10 | test9 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph | | file://:0:0:0:0 | Panicf | log.Panicf |
| file://:0:0:0:0 | Panicln | log.Logger.Panicln |
| file://:0:0:0:0 | Panicln | log.Panicln |
| file://:0:0:0:0 | panic | panic |
| noretfunctions.go:8:6:8:12 | isNoRet | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.isNoRet |
| noretfunctions.go:20:6:20:22 | noRetUsesLogFatal | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.noRetUsesLogFatal |
| noretfunctions.go:24:6:24:23 | noRetUsesLogFatalf | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.noRetUsesLogFatalf |
| stmts7.go:10:6:10:15 | canRecover | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.canRecover |
| stmts.go:10:6:10:10 | test5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test5 |
| stmts.go:46:6:46:10 | test6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test6 |
| stmts.go:112:6:112:10 | test9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test9 |

View File

@@ -2,4 +2,4 @@ import go
from Function f from Function f
where not f.mayReturnNormally() where not f.mayReturnNormally()
select f, f.getPackage() select f, f.getQualifiedName()

View File

@@ -9,9 +9,9 @@ import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
import utils.test.InlineFlowTest import utils.test.InlineFlowTest
module Config implements DataFlow::ConfigSig { module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { sourceNode(src, "qltest") } predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") }
predicate isSink(DataFlow::Node src) { sinkNode(src, "qltest") } predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") }
} }
import ValueFlowTest<Config> import ValueFlowTest<Config>

View File

@@ -0,0 +1,2 @@
reverseRead
| main.go:23:3:23:5 | out | Origin of readStep is missing a PostUpdateNode. |

View File

@@ -4,7 +4,7 @@ func source() string {
return "untrusted data" return "untrusted data"
} }
func sink(string) { func sink(any) {
} }
type A struct { type A struct {
@@ -19,6 +19,10 @@ func functionWithVarArgsParameter(s ...string) string {
return s[1] return s[1]
} }
func functionWithVarArgsOutParameter(in string, out ...*string) {
*out[0] = in
}
func functionWithSliceOfStructsParameter(s []A) string { func functionWithSliceOfStructsParameter(s []A) string {
return s[1].f return s[1].f
} }
@@ -38,6 +42,12 @@ func main() {
sink(functionWithVarArgsParameter(sSlice...)) // $ hasValueFlow="call to functionWithVarArgsParameter" sink(functionWithVarArgsParameter(sSlice...)) // $ hasValueFlow="call to functionWithVarArgsParameter"
sink(functionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to functionWithVarArgsParameter" sink(functionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to functionWithVarArgsParameter"
var out1 *string
var out2 *string
functionWithVarArgsOutParameter(source(), out1, out2)
sink(out1) // $ MISSING: hasValueFlow="out1"
sink(out2) // $ MISSING: hasValueFlow="out2"
sliceOfStructs := []A{{f: source()}} sliceOfStructs := []A{{f: source()}}
sink(sliceOfStructs[0].f) // $ hasValueFlow="selection of f" sink(sliceOfStructs[0].f) // $ hasValueFlow="selection of f"

View File

@@ -0,0 +1,2 @@
invalidModelRow
testFailures

View File

@@ -0,0 +1,21 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: summaryModel
data:
- ["github.com/nonexistent/test", "", False, "FunctionWithParameter", "", "", "Argument[0]", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "FunctionWithSliceParameter", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "FunctionWithVarArgsParameter", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "FunctionWithVarArgsOutParameter", "", "", "Argument[0]", "Argument[1].ArrayElement", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "FunctionWithSliceOfStructsParameter", "", "", "Argument[0].ArrayElement.Field[github.com/nonexistent/test.A.Field]", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "FunctionWithVarArgsOfStructsParameter", "", "", "Argument[0].ArrayElement.Field[github.com/nonexistent/test.A.Field]", "ReturnValue", "value", "manual"]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/test", "", False, "VariadicSource", "", "", "Argument[0]", "qltest", "manual"]
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/nonexistent/test", "", False, "VariadicSink", "", "", "Argument[0]", "qltest", "manual"]

View File

@@ -0,0 +1,22 @@
import go
import semmle.go.dataflow.ExternalFlow
import ModelValidation
import utils.test.InlineFlowTest
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
sourceNode(source, "qltest")
or
exists(Function fn | fn.hasQualifiedName(_, ["source", "taint"]) |
source = fn.getACall().getResult()
)
}
predicate isSink(DataFlow::Node sink) {
sinkNode(sink, "qltest")
or
exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument())
}
}
import FlowTest<Config, Config>

View File

@@ -0,0 +1,5 @@
module semmle.go.Packages
go 1.25
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000

View File

@@ -0,0 +1,56 @@
package main
import (
"github.com/nonexistent/test"
)
func source() string {
return "untrusted data"
}
func sink(any) {
}
func main() {
s := source()
sink(test.FunctionWithParameter(s)) // $ hasValueFlow="call to FunctionWithParameter"
stringSlice := []string{source()}
sink(stringSlice[0]) // $ hasValueFlow="index expression"
s0 := ""
s1 := source()
sSlice := []string{s0, s1}
sink(test.FunctionWithParameter(sSlice[1])) // $ hasValueFlow="call to FunctionWithParameter"
sink(test.FunctionWithSliceParameter(sSlice)) // $ hasValueFlow="call to FunctionWithSliceParameter"
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ hasValueFlow="call to FunctionWithVarArgsParameter"
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to FunctionWithVarArgsParameter"
var out1 *string
var out2 *string
test.FunctionWithVarArgsOutParameter(source(), out1, out2)
sink(out1) // $ MISSING: hasValueFlow="out1"
sink(out2) // $ MISSING: hasValueFlow="out2"
sliceOfStructs := []test.A{{Field: source()}}
sink(sliceOfStructs[0].Field) // $ hasValueFlow="selection of Field"
a0 := test.A{Field: ""}
a1 := test.A{Field: source()}
aSlice := []test.A{a0, a1}
sink(test.FunctionWithSliceOfStructsParameter(aSlice)) // $ hasValueFlow="call to FunctionWithSliceOfStructsParameter"
sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
var variadicSource string
test.VariadicSource(&variadicSource)
sink(variadicSource) // $ MISSING: hasTaintFlow="variadicSource"
sink(&variadicSource) // $ MISSING: hasTaintFlow="&..."
var variadicSourcePtr *string
test.VariadicSource(variadicSourcePtr)
sink(variadicSourcePtr) // $ MISSING: hasTaintFlow="variadicSourcePtr"
sink(*variadicSourcePtr) // $ MISSING: hasTaintFlow="star expression"
test.VariadicSink(source()) // $ hasTaintFlow="[]type{args}"
}

View File

@@ -0,0 +1,32 @@
package test
type A struct {
Field string
}
func FunctionWithParameter(s string) string {
return ""
}
func FunctionWithSliceParameter(s []string) string {
return ""
}
func FunctionWithVarArgsParameter(s ...string) string {
return ""
}
func FunctionWithVarArgsOutParameter(in string, out ...*string) {
}
func FunctionWithSliceOfStructsParameter(s []A) string {
return ""
}
func FunctionWithVarArgsOfStructsParameter(s ...A) string {
return ""
}
func VariadicSource(s ...*string) {}
func VariadicSink(s ...string) {}

View File

@@ -0,0 +1,3 @@
# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
## explicit
github.com/nonexistent/test

View File

@@ -20,6 +20,9 @@ class SummaryModelTest extends DataFlow::FunctionModel {
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsParameter") and this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsParameter") and
(inp.isParameter(_) and outp.isResult()) (inp.isParameter(_) and outp.isResult())
or or
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsOutParameter") and
(inp.isParameter(0) and outp.isParameter(any(int i | i >= 1)))
or
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceOfStructsParameter") and this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceOfStructsParameter") and
(inp.isParameter(0) and outp.isResult()) (inp.isParameter(0) and outp.isResult())
or or

View File

@@ -1,5 +1,5 @@
module semmle.go.Packages module semmle.go.Packages
go 1.17 go 1.25
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000 require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000

View File

@@ -8,7 +8,7 @@ func source() string {
return "untrusted data" return "untrusted data"
} }
func sink(string) { func sink(any) {
} }
func main() { func main() {
@@ -21,10 +21,17 @@ func main() {
s0 := "" s0 := ""
s1 := source() s1 := source()
sSlice := []string{s0, s1} sSlice := []string{s0, s1}
sink(test.FunctionWithParameter(sSlice[1])) // $ hasValueFlow="call to FunctionWithParameter" sink(test.FunctionWithParameter(sSlice[1])) // $ hasValueFlow="call to FunctionWithParameter"
sink(test.FunctionWithSliceParameter(sSlice)) // $ hasTaintFlow="call to FunctionWithSliceParameter" MISSING: hasValueFlow="call to FunctionWithSliceParameter" sink(test.FunctionWithSliceParameter(sSlice)) // $ hasTaintFlow="call to FunctionWithSliceParameter" MISSING: hasValueFlow="call to FunctionWithSliceParameter"
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ hasTaintFlow="call to FunctionWithVarArgsParameter" MISSING: hasValueFlow="call to FunctionWithVarArgsParameter" sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ hasTaintFlow="call to FunctionWithVarArgsParameter" MISSING: hasValueFlow="call to FunctionWithVarArgsParameter"
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsParameter" randomFunctionWithMoreThanOneParameter(1, 2, 3, 4, 5) // This is needed to make the next line pass, because we need to have seen a call to a function with at least 2 parameters for ParameterInput to exist with index 1.
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to FunctionWithVarArgsParameter"
var out1 *string
var out2 *string
test.FunctionWithVarArgsOutParameter(source(), out1, out2)
sink(out1) // $ hasValueFlow="out1"
sink(out2) // $ hasValueFlow="out2"
sliceOfStructs := []test.A{{Field: source()}} sliceOfStructs := []test.A{{Field: source()}}
sink(sliceOfStructs[0].Field) // $ hasValueFlow="selection of Field" sink(sliceOfStructs[0].Field) // $ hasValueFlow="selection of Field"
@@ -37,3 +44,6 @@ func main() {
sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsOfStructsParameter" sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsOfStructsParameter" sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
} }
func randomFunctionWithMoreThanOneParameter(i1, i2, i3, i4, i5 int) {
}

View File

@@ -16,6 +16,9 @@ func FunctionWithVarArgsParameter(s ...string) string {
return "" return ""
} }
func FunctionWithVarArgsOutParameter(in string, out ...*string) {
}
func FunctionWithSliceOfStructsParameter(s []A) string { func FunctionWithSliceOfStructsParameter(s []A) string {
return "" return ""
} }

View File

@@ -15,62 +15,6 @@ func TaintStepTest_LogNew_B0I0O0(sourceCQL interface{}) interface{} {
return intoWriter414 return intoWriter414
} }
func TaintStepTest_LogLoggerFatal_B0I0O0(sourceCQL interface{}) interface{} {
fromInterface518 := sourceCQL.(interface{})
var intoLogger650 log.Logger
intoLogger650.Fatal(fromInterface518)
return intoLogger650
}
func TaintStepTest_LogLoggerFatalf_B0I0O0(sourceCQL interface{}) interface{} {
fromString784 := sourceCQL.(string)
var intoLogger957 log.Logger
intoLogger957.Fatalf(fromString784, nil)
return intoLogger957
}
func TaintStepTest_LogLoggerFatalf_B0I1O0(sourceCQL interface{}) interface{} {
fromInterface520 := sourceCQL.(interface{})
var intoLogger443 log.Logger
intoLogger443.Fatalf("", fromInterface520)
return intoLogger443
}
func TaintStepTest_LogLoggerFatalln_B0I0O0(sourceCQL interface{}) interface{} {
fromInterface127 := sourceCQL.(interface{})
var intoLogger483 log.Logger
intoLogger483.Fatalln(fromInterface127)
return intoLogger483
}
func TaintStepTest_LogLoggerPanic_B0I0O0(sourceCQL interface{}) interface{} {
fromInterface989 := sourceCQL.(interface{})
var intoLogger982 log.Logger
intoLogger982.Panic(fromInterface989)
return intoLogger982
}
func TaintStepTest_LogLoggerPanicf_B0I0O0(sourceCQL interface{}) interface{} {
fromString417 := sourceCQL.(string)
var intoLogger584 log.Logger
intoLogger584.Panicf(fromString417, nil)
return intoLogger584
}
func TaintStepTest_LogLoggerPanicf_B0I1O0(sourceCQL interface{}) interface{} {
fromInterface991 := sourceCQL.(interface{})
var intoLogger881 log.Logger
intoLogger881.Panicf("", fromInterface991)
return intoLogger881
}
func TaintStepTest_LogLoggerPanicln_B0I0O0(sourceCQL interface{}) interface{} {
fromInterface186 := sourceCQL.(interface{})
var intoLogger284 log.Logger
intoLogger284.Panicln(fromInterface186)
return intoLogger284
}
func TaintStepTest_LogLoggerPrint_B0I0O0(sourceCQL interface{}) interface{} { func TaintStepTest_LogLoggerPrint_B0I0O0(sourceCQL interface{}) interface{} {
fromInterface908 := sourceCQL.(interface{}) fromInterface908 := sourceCQL.(interface{})
var intoLogger137 log.Logger var intoLogger137 log.Logger
@@ -125,46 +69,6 @@ func RunAllTaints_Log() {
out := TaintStepTest_LogNew_B0I0O0(source) out := TaintStepTest_LogNew_B0I0O0(source)
sink(0, out) sink(0, out)
} }
{
source := newSource(1)
out := TaintStepTest_LogLoggerFatal_B0I0O0(source)
sink(1, out)
}
{
source := newSource(2)
out := TaintStepTest_LogLoggerFatalf_B0I0O0(source)
sink(2, out)
}
{
source := newSource(3)
out := TaintStepTest_LogLoggerFatalf_B0I1O0(source)
sink(3, out)
}
{
source := newSource(4)
out := TaintStepTest_LogLoggerFatalln_B0I0O0(source)
sink(4, out)
}
{
source := newSource(5)
out := TaintStepTest_LogLoggerPanic_B0I0O0(source)
sink(5, out)
}
{
source := newSource(6)
out := TaintStepTest_LogLoggerPanicf_B0I0O0(source)
sink(6, out)
}
{
source := newSource(7)
out := TaintStepTest_LogLoggerPanicf_B0I1O0(source)
sink(7, out)
}
{
source := newSource(8)
out := TaintStepTest_LogLoggerPanicln_B0I0O0(source)
sink(8, out)
}
{ {
source := newSource(9) source := newSource(9)
out := TaintStepTest_LogLoggerPrint_B0I0O0(source) out := TaintStepTest_LogLoggerPrint_B0I0O0(source)

View File

@@ -3,9 +3,9 @@ reverseRead
| LogInjection.go:33:14:33:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:33:14:33:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:34:18:34:20 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:34:18:34:20 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:35:14:35:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:35:14:35:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:447:14:447:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:551:14:551:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:455:14:455:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:559:14:559:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:463:14:463:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:567:14:567:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:498:14:498:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:602:14:602:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:499:14:499:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:603:14:603:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| LogInjection.go:724:12:724:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | LogInjection.go:828:12:828:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |

View File

@@ -49,22 +49,22 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
log.Printf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password" log.Printf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
log.Println("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" log.Println("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
if testFlag == "true" { if testFlag == "1" {
log.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" log.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
} }
if testFlag == "true" { if testFlag == "2" {
log.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password" log.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
} }
if testFlag == "true" { if testFlag == "3" {
log.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" log.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
} }
if testFlag == "true" { if testFlag == "4" {
log.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" log.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
} }
if testFlag == "true" { if testFlag == "5" {
log.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password" log.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
} }
if testFlag == "true" { if testFlag == "6" {
log.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" log.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
} }
@@ -72,12 +72,24 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
logger.Print("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" logger.Print("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
logger.Printf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password" logger.Printf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
logger.Println("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" logger.Println("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
logger.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" if testFlag == "7" {
logger.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password" logger.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
logger.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" }
logger.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" if testFlag == "8" {
logger.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password" logger.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
logger.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password" }
if testFlag == "9" {
logger.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "10" {
logger.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "11" {
logger.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "12" {
logger.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
} }
// k8s.io/klog // k8s.io/klog
{ {
@@ -91,12 +103,24 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
klog.Error(username) // $ hasTaintFlow="username" klog.Error(username) // $ hasTaintFlow="username"
klog.Errorf(username) // $ hasTaintFlow="username" klog.Errorf(username) // $ hasTaintFlow="username"
klog.Errorln(username) // $ hasTaintFlow="username" klog.Errorln(username) // $ hasTaintFlow="username"
klog.Fatal(username) // $ hasTaintFlow="username" if testFlag == "77" {
klog.Fatalf(username) // $ hasTaintFlow="username" klog.Fatal(username) // $ hasTaintFlow="username"
klog.Fatalln(username) // $ hasTaintFlow="username" }
klog.Exit(username) // $ hasTaintFlow="username" if testFlag == "78" {
klog.Exitf(username) // $ hasTaintFlow="username" klog.Fatalf(username) // $ hasTaintFlow="username"
klog.Exitln(username) // $ hasTaintFlow="username" }
if testFlag == "79" {
klog.Fatalln(username) // $ hasTaintFlow="username"
}
if testFlag == "80" {
klog.Exit(username) // $ hasTaintFlow="username"
}
if testFlag == "81" {
klog.Exitf(username) // $ hasTaintFlow="username"
}
if testFlag == "82" {
klog.Exitln(username) // $ hasTaintFlow="username"
}
} }
// astaxie/beego // astaxie/beego
{ {
@@ -161,14 +185,30 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
glog.ErrorDepth(0, username) // $ hasTaintFlow="username" glog.ErrorDepth(0, username) // $ hasTaintFlow="username"
glog.Errorf(username) // $ hasTaintFlow="username" glog.Errorf(username) // $ hasTaintFlow="username"
glog.Errorln(username) // $ hasTaintFlow="username" glog.Errorln(username) // $ hasTaintFlow="username"
glog.Fatal(username) // $ hasTaintFlow="username" if testFlag == "83" {
glog.FatalDepth(0, username) // $ hasTaintFlow="username" glog.Fatal(username) // $ hasTaintFlow="username"
glog.Fatalf(username) // $ hasTaintFlow="username" }
glog.Fatalln(username) // $ hasTaintFlow="username" if testFlag == "84" {
glog.Exit(username) // $ hasTaintFlow="username" glog.FatalDepth(0, username) // $ hasTaintFlow="username"
glog.ExitDepth(0, username) // $ hasTaintFlow="username" }
glog.Exitf(username) // $ hasTaintFlow="username" if testFlag == "85" {
glog.Exitln(username) // $ hasTaintFlow="username" glog.Fatalf(username) // $ hasTaintFlow="username"
}
if testFlag == "86" {
glog.Fatalln(username) // $ hasTaintFlow="username"
}
if testFlag == "87" {
glog.Exit(username) // $ hasTaintFlow="username"
}
if testFlag == "88" {
glog.ExitDepth(0, username) // $ hasTaintFlow="username"
}
if testFlag == "89" {
glog.Exitf(username) // $ hasTaintFlow="username"
}
if testFlag == "90" {
glog.Exitln(username) // $ hasTaintFlow="username"
}
} }
// sirupsen/logrus // sirupsen/logrus
@@ -179,26 +219,42 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
logger := logrus.New() logger := logrus.New()
entry := logrus.NewEntry(logger) entry := logrus.NewEntry(logger)
logrus.Debug(username) // $ hasTaintFlow="username" logrus.Debug(username) // $ hasTaintFlow="username"
logrus.Debugf(username, "") // $ hasTaintFlow="username" logrus.Debugf(username, "") // $ hasTaintFlow="username"
logrus.Debugf("", username) // $ hasTaintFlow="username" logrus.Debugf("", username) // $ hasTaintFlow="username"
logrus.Debugln(username) // $ hasTaintFlow="username" logrus.Debugln(username) // $ hasTaintFlow="username"
logrus.Error(username) // $ hasTaintFlow="username" logrus.Error(username) // $ hasTaintFlow="username"
logrus.Errorf(username, "") // $ hasTaintFlow="username" logrus.Errorf(username, "") // $ hasTaintFlow="username"
logrus.Errorf("", username) // $ hasTaintFlow="username" logrus.Errorf("", username) // $ hasTaintFlow="username"
logrus.Errorln(username) // $ hasTaintFlow="username" logrus.Errorln(username) // $ hasTaintFlow="username"
logrus.Fatal(username) // $ hasTaintFlow="username" if testFlag == "13" {
logrus.Fatalf(username, "") // $ hasTaintFlow="username" logrus.Fatal(username) // $ hasTaintFlow="username"
logrus.Fatalf("", username) // $ hasTaintFlow="username" }
logrus.Fatalln(username) // $ hasTaintFlow="username" if testFlag == "14" {
logrus.Info(username) // $ hasTaintFlow="username" logrus.Fatalf(username, "") // $ hasTaintFlow="username"
logrus.Infof(username, "") // $ hasTaintFlow="username" }
logrus.Infof("", username) // $ hasTaintFlow="username" if testFlag == "15" {
logrus.Infoln(username) // $ hasTaintFlow="username" logrus.Fatalf("", username) // $ hasTaintFlow="username"
logrus.Panic(username) // $ hasTaintFlow="username" }
logrus.Panicf(username, "") // $ hasTaintFlow="username" if testFlag == "16" {
logrus.Panicf("", username) // $ hasTaintFlow="username" logrus.Fatalln(username) // $ hasTaintFlow="username"
logrus.Panicln(username) // $ hasTaintFlow="username" }
logrus.Info(username) // $ hasTaintFlow="username"
logrus.Infof(username, "") // $ hasTaintFlow="username"
logrus.Infof("", username) // $ hasTaintFlow="username"
logrus.Infoln(username) // $ hasTaintFlow="username"
if testFlag == "17" {
logrus.Panic(username) // $ hasTaintFlow="username"
}
if testFlag == "18" {
logrus.Panicf(username, "") // $ hasTaintFlow="username"
}
if testFlag == "19" {
logrus.Panicf("", username) // $ hasTaintFlow="username"
}
if testFlag == "20" {
logrus.Panicln(username) // $ hasTaintFlow="username"
}
logrus.Print(username) // $ hasTaintFlow="username" logrus.Print(username) // $ hasTaintFlow="username"
logrus.Printf(username, "") // $ hasTaintFlow="username" logrus.Printf(username, "") // $ hasTaintFlow="username"
logrus.Printf("", username) // $ hasTaintFlow="username" logrus.Printf("", username) // $ hasTaintFlow="username"
@@ -220,30 +276,46 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
logrus.WithField("", username) // $ hasTaintFlow="username" logrus.WithField("", username) // $ hasTaintFlow="username"
logrus.WithFields(fields) // $ hasTaintFlow="fields" logrus.WithFields(fields) // $ hasTaintFlow="fields"
entry.Debug(username) // $ hasTaintFlow="username" entry.Debug(username) // $ hasTaintFlow="username"
entry.Debugf(username, "") // $ hasTaintFlow="username" entry.Debugf(username, "") // $ hasTaintFlow="username"
entry.Debugf("", username) // $ hasTaintFlow="username" entry.Debugf("", username) // $ hasTaintFlow="username"
entry.Debugln(username) // $ hasTaintFlow="username" entry.Debugln(username) // $ hasTaintFlow="username"
entry.Error(username) // $ hasTaintFlow="username" entry.Error(username) // $ hasTaintFlow="username"
entry.Errorf(username, "") // $ hasTaintFlow="username" entry.Errorf(username, "") // $ hasTaintFlow="username"
entry.Errorf("", username) // $ hasTaintFlow="username" entry.Errorf("", username) // $ hasTaintFlow="username"
entry.Errorln(username) // $ hasTaintFlow="username" entry.Errorln(username) // $ hasTaintFlow="username"
entry.Fatal(username) // $ hasTaintFlow="username" if testFlag == "21" {
entry.Fatalf(username, "") // $ hasTaintFlow="username" entry.Fatal(username) // $ hasTaintFlow="username"
entry.Fatalf("", username) // $ hasTaintFlow="username" }
entry.Fatalln(username) // $ hasTaintFlow="username" if testFlag == "22" {
entry.Info(username) // $ hasTaintFlow="username" entry.Fatalf(username, "") // $ hasTaintFlow="username"
entry.Infof(username, "") // $ hasTaintFlow="username" }
entry.Infof("", username) // $ hasTaintFlow="username" if testFlag == "23" {
entry.Infoln(username) // $ hasTaintFlow="username" entry.Fatalf("", username) // $ hasTaintFlow="username"
entry.Log(0, username) // $ hasTaintFlow="username" }
entry.Logf(0, username, "") // $ hasTaintFlow="username" if testFlag == "24" {
entry.Logf(0, "", username) // $ hasTaintFlow="username" entry.Fatalln(username) // $ hasTaintFlow="username"
entry.Logln(0, username) // $ hasTaintFlow="username" }
entry.Panic(username) // $ hasTaintFlow="username" entry.Info(username) // $ hasTaintFlow="username"
entry.Panicf(username, "") // $ hasTaintFlow="username" entry.Infof(username, "") // $ hasTaintFlow="username"
entry.Panicf("", username) // $ hasTaintFlow="username" entry.Infof("", username) // $ hasTaintFlow="username"
entry.Panicln(username) // $ hasTaintFlow="username" entry.Infoln(username) // $ hasTaintFlow="username"
entry.Log(0, username) // $ hasTaintFlow="username"
entry.Logf(0, username, "") // $ hasTaintFlow="username"
entry.Logf(0, "", username) // $ hasTaintFlow="username"
entry.Logln(0, username) // $ hasTaintFlow="username"
if testFlag == "25" {
entry.Panic(username) // $ hasTaintFlow="username"
}
if testFlag == "26" {
entry.Panicf(username, "") // $ hasTaintFlow="username"
}
if testFlag == "27" {
entry.Panicf("", username) // $ hasTaintFlow="username"
}
if testFlag == "28" {
entry.Panicln(username) // $ hasTaintFlow="username"
}
entry.Print(username) // $ hasTaintFlow="username" entry.Print(username) // $ hasTaintFlow="username"
entry.Printf(username, "") // $ hasTaintFlow="username" entry.Printf(username, "") // $ hasTaintFlow="username"
entry.Printf("", username) // $ hasTaintFlow="username" entry.Printf("", username) // $ hasTaintFlow="username"
@@ -265,30 +337,46 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
entry.WithField("", username) // $ hasTaintFlow="username" entry.WithField("", username) // $ hasTaintFlow="username"
entry.WithFields(fields) // $ hasTaintFlow="fields" entry.WithFields(fields) // $ hasTaintFlow="fields"
logger.Debug(username) // $ hasTaintFlow="username" logger.Debug(username) // $ hasTaintFlow="username"
logger.Debugf(username, "") // $ hasTaintFlow="username" logger.Debugf(username, "") // $ hasTaintFlow="username"
logger.Debugf("", username) // $ hasTaintFlow="username" logger.Debugf("", username) // $ hasTaintFlow="username"
logger.Debugln(username) // $ hasTaintFlow="username" logger.Debugln(username) // $ hasTaintFlow="username"
logger.Error(username) // $ hasTaintFlow="username" logger.Error(username) // $ hasTaintFlow="username"
logger.Errorf(username, "") // $ hasTaintFlow="username" logger.Errorf(username, "") // $ hasTaintFlow="username"
logger.Errorf("", username) // $ hasTaintFlow="username" logger.Errorf("", username) // $ hasTaintFlow="username"
logger.Errorln(username) // $ hasTaintFlow="username" logger.Errorln(username) // $ hasTaintFlow="username"
logger.Fatal(username) // $ hasTaintFlow="username" if testFlag == "29" {
logger.Fatalf(username, "") // $ hasTaintFlow="username" logger.Fatal(username) // $ hasTaintFlow="username"
logger.Fatalf("", username) // $ hasTaintFlow="username" }
logger.Fatalln(username) // $ hasTaintFlow="username" if testFlag == "30" {
logger.Info(username) // $ hasTaintFlow="username" logger.Fatalf(username, "") // $ hasTaintFlow="username"
logger.Infof(username, "") // $ hasTaintFlow="username" }
logger.Infof("", username) // $ hasTaintFlow="username" if testFlag == "31" {
logger.Infoln(username) // $ hasTaintFlow="username" logger.Fatalf("", username) // $ hasTaintFlow="username"
logger.Log(0, username) // $ hasTaintFlow="username" }
logger.Logf(0, username, "") // $ hasTaintFlow="username" if testFlag == "32" {
logger.Logf(0, "", username) // $ hasTaintFlow="username" logger.Fatalln(username) // $ hasTaintFlow="username"
logger.Logln(0, username) // $ hasTaintFlow="username" }
logger.Panic(username) // $ hasTaintFlow="username" logger.Info(username) // $ hasTaintFlow="username"
logger.Panicf(username, "") // $ hasTaintFlow="username" logger.Infof(username, "") // $ hasTaintFlow="username"
logger.Panicf("", username) // $ hasTaintFlow="username" logger.Infof("", username) // $ hasTaintFlow="username"
logger.Panicln(username) // $ hasTaintFlow="username" logger.Infoln(username) // $ hasTaintFlow="username"
logger.Log(0, username) // $ hasTaintFlow="username"
logger.Logf(0, username, "") // $ hasTaintFlow="username"
logger.Logf(0, "", username) // $ hasTaintFlow="username"
logger.Logln(0, username) // $ hasTaintFlow="username"
if testFlag == "33" {
logger.Panic(username) // $ hasTaintFlow="username"
}
if testFlag == "34" {
logger.Panicf(username, "") // $ hasTaintFlow="username"
}
if testFlag == "35" {
logger.Panicf("", username) // $ hasTaintFlow="username"
}
if testFlag == "36" {
logger.Panicln(username) // $ hasTaintFlow="username"
}
logger.Print(username) // $ hasTaintFlow="username" logger.Print(username) // $ hasTaintFlow="username"
logger.Printf(username, "") // $ hasTaintFlow="username" logger.Printf(username, "") // $ hasTaintFlow="username"
logger.Printf("", username) // $ hasTaintFlow="username" logger.Printf("", username) // $ hasTaintFlow="username"
@@ -311,26 +399,42 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
logger.WithFields(fields) // $ hasTaintFlow="fields" logger.WithFields(fields) // $ hasTaintFlow="fields"
var fieldlogger logrus.FieldLogger = entry var fieldlogger logrus.FieldLogger = entry
fieldlogger.Debug(username) // $ hasTaintFlow="username" fieldlogger.Debug(username) // $ hasTaintFlow="username"
fieldlogger.Debugf(username, "") // $ hasTaintFlow="username" fieldlogger.Debugf(username, "") // $ hasTaintFlow="username"
fieldlogger.Debugf("", username) // $ hasTaintFlow="username" fieldlogger.Debugf("", username) // $ hasTaintFlow="username"
fieldlogger.Debugln(username) // $ hasTaintFlow="username" fieldlogger.Debugln(username) // $ hasTaintFlow="username"
fieldlogger.Error(username) // $ hasTaintFlow="username" fieldlogger.Error(username) // $ hasTaintFlow="username"
fieldlogger.Errorf(username, "") // $ hasTaintFlow="username" fieldlogger.Errorf(username, "") // $ hasTaintFlow="username"
fieldlogger.Errorf("", username) // $ hasTaintFlow="username" fieldlogger.Errorf("", username) // $ hasTaintFlow="username"
fieldlogger.Errorln(username) // $ hasTaintFlow="username" fieldlogger.Errorln(username) // $ hasTaintFlow="username"
fieldlogger.Fatal(username) // $ hasTaintFlow="username" if testFlag == "37" {
fieldlogger.Fatalf(username, "") // $ hasTaintFlow="username" fieldlogger.Fatal(username) // $ hasTaintFlow="username"
fieldlogger.Fatalf("", username) // $ hasTaintFlow="username" }
fieldlogger.Fatalln(username) // $ hasTaintFlow="username" if testFlag == "38" {
fieldlogger.Info(username) // $ hasTaintFlow="username" fieldlogger.Fatalf(username, "") // $ hasTaintFlow="username"
fieldlogger.Infof(username, "") // $ hasTaintFlow="username" }
fieldlogger.Infof("", username) // $ hasTaintFlow="username" if testFlag == "39" {
fieldlogger.Infoln(username) // $ hasTaintFlow="username" fieldlogger.Fatalf("", username) // $ hasTaintFlow="username"
fieldlogger.Panic(username) // $ hasTaintFlow="username" }
fieldlogger.Panicf(username, "") // $ hasTaintFlow="username" if testFlag == "40" {
fieldlogger.Panicf("", username) // $ hasTaintFlow="username" fieldlogger.Fatalln(username) // $ hasTaintFlow="username"
fieldlogger.Panicln(username) // $ hasTaintFlow="username" }
fieldlogger.Info(username) // $ hasTaintFlow="username"
fieldlogger.Infof(username, "") // $ hasTaintFlow="username"
fieldlogger.Infof("", username) // $ hasTaintFlow="username"
fieldlogger.Infoln(username) // $ hasTaintFlow="username"
if testFlag == "41" {
fieldlogger.Panic(username) // $ hasTaintFlow="username"
}
if testFlag == "42" {
fieldlogger.Panicf(username, "") // $ hasTaintFlow="username"
}
if testFlag == "43" {
fieldlogger.Panicf("", username) // $ hasTaintFlow="username"
}
if testFlag == "44" {
fieldlogger.Panicln(username) // $ hasTaintFlow="username"
}
fieldlogger.Print(username) // $ hasTaintFlow="username" fieldlogger.Print(username) // $ hasTaintFlow="username"
fieldlogger.Printf(username, "") // $ hasTaintFlow="username" fieldlogger.Printf(username, "") // $ hasTaintFlow="username"
fieldlogger.Printf("", username) // $ hasTaintFlow="username" fieldlogger.Printf("", username) // $ hasTaintFlow="username"
@@ -366,11 +470,11 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
logger.DPanic(username) // $ hasTaintFlow="username" logger.DPanic(username) // $ hasTaintFlow="username"
logger.Debug(username) // $ hasTaintFlow="username" logger.Debug(username) // $ hasTaintFlow="username"
logger.Error(username) // $ hasTaintFlow="username" logger.Error(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "45" {
logger.Fatal(username) // $ hasTaintFlow="username" logger.Fatal(username) // $ hasTaintFlow="username"
} }
logger.Info(username) // $ hasTaintFlow="username" logger.Info(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "46" {
logger.Panic(username) // $ hasTaintFlow="username" logger.Panic(username) // $ hasTaintFlow="username"
} }
logger.Warn(username) // $ hasTaintFlow="username" logger.Warn(username) // $ hasTaintFlow="username"
@@ -382,33 +486,33 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
sLogger.DPanic(username) // $ hasTaintFlow="username" sLogger.DPanic(username) // $ hasTaintFlow="username"
sLogger.Debug(username) // $ hasTaintFlow="username" sLogger.Debug(username) // $ hasTaintFlow="username"
sLogger.Error(username) // $ hasTaintFlow="username" sLogger.Error(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "47" {
sLogger.Fatal(username) // $ hasTaintFlow="username" sLogger.Fatal(username) // $ hasTaintFlow="username"
} }
sLogger.Info(username) // $ hasTaintFlow="username" sLogger.Info(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "48" {
sLogger.Panic(username) // $ hasTaintFlow="username" sLogger.Panic(username) // $ hasTaintFlow="username"
} }
sLogger.Warn(username) // $ hasTaintFlow="username" sLogger.Warn(username) // $ hasTaintFlow="username"
sLogger.DPanicf(username) // $ hasTaintFlow="username" sLogger.DPanicf(username) // $ hasTaintFlow="username"
sLogger.Debugf(username) // $ hasTaintFlow="username" sLogger.Debugf(username) // $ hasTaintFlow="username"
sLogger.Errorf(username) // $ hasTaintFlow="username" sLogger.Errorf(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "49" {
sLogger.Fatalf(username) // $ hasTaintFlow="username" sLogger.Fatalf(username) // $ hasTaintFlow="username"
} }
sLogger.Infof(username) // $ hasTaintFlow="username" sLogger.Infof(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "50" {
sLogger.Panicf(username) // $ hasTaintFlow="username" sLogger.Panicf(username) // $ hasTaintFlow="username"
} }
sLogger.Warnf(username) // $ hasTaintFlow="username" sLogger.Warnf(username) // $ hasTaintFlow="username"
sLogger.DPanicw(username) // $ hasTaintFlow="username" sLogger.DPanicw(username) // $ hasTaintFlow="username"
sLogger.Debugw(username) // $ hasTaintFlow="username" sLogger.Debugw(username) // $ hasTaintFlow="username"
sLogger.Errorw(username) // $ hasTaintFlow="username" sLogger.Errorw(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "51" {
sLogger.Fatalw(username) // $ hasTaintFlow="username" sLogger.Fatalw(username) // $ hasTaintFlow="username"
} }
sLogger.Infow(username) // $ hasTaintFlow="username" sLogger.Infow(username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "52" {
sLogger.Panicw(username) // $ hasTaintFlow="username" sLogger.Panicw(username) // $ hasTaintFlow="username"
} }
sLogger.Warnw(username) // $ hasTaintFlow="username" sLogger.Warnw(username) // $ hasTaintFlow="username"
@@ -515,10 +619,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
verbose.Infof("user %q logged in.\n", username) verbose.Infof("user %q logged in.\n", username)
klog.Infof("user %q logged in.\n", username) klog.Infof("user %q logged in.\n", username)
klog.Errorf("user %q logged in.\n", username) klog.Errorf("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "53" {
klog.Fatalf("user %q logged in.\n", username) klog.Fatalf("user %q logged in.\n", username)
} }
if testFlag == " true" { if testFlag == "54" {
klog.Exitf("user %q logged in.\n", username) klog.Exitf("user %q logged in.\n", username)
} }
} }
@@ -534,10 +638,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
glog.Infof("user %q logged in.\n", username) glog.Infof("user %q logged in.\n", username)
glog.Errorf("user %q logged in.\n", username) glog.Errorf("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "55" {
glog.Fatalf("user %q logged in.\n", username) glog.Fatalf("user %q logged in.\n", username)
} }
if testFlag == " true" { if testFlag == "56" {
glog.Exitf("user %q logged in.\n", username) glog.Exitf("user %q logged in.\n", username)
} }
} }
@@ -545,11 +649,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
{ {
logrus.Debugf("user %q logged in.\n", username) logrus.Debugf("user %q logged in.\n", username)
logrus.Errorf("user %q logged in.\n", username) logrus.Errorf("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "57" {
logrus.Fatalf("user %q logged in.\n", username) logrus.Fatalf("user %q logged in.\n", username)
} }
logrus.Infof("user %q logged in.\n", username) logrus.Infof("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "58" {
logrus.Panicf("user %q logged in.\n", username) logrus.Panicf("user %q logged in.\n", username)
} }
logrus.Printf("user %q logged in.\n", username) logrus.Printf("user %q logged in.\n", username)
@@ -561,12 +665,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
entry := logrus.WithFields(fields) entry := logrus.WithFields(fields)
entry.Debugf("user %q logged in.\n", username) entry.Debugf("user %q logged in.\n", username)
entry.Errorf("user %q logged in.\n", username) entry.Errorf("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "59" {
entry.Fatalf("user %q logged in.\n", username) entry.Fatalf("user %q logged in.\n", username)
} }
entry.Infof("user %q logged in.\n", username) entry.Infof("user %q logged in.\n", username)
entry.Logf(0, "user %q logged in.\n", username) entry.Logf(0, "user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "60" {
entry.Panicf("user %q logged in.\n", username) entry.Panicf("user %q logged in.\n", username)
} }
entry.Printf("user %q logged in.\n", username) entry.Printf("user %q logged in.\n", username)
@@ -577,12 +681,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
logger := entry.Logger logger := entry.Logger
logger.Debugf("user %q logged in.\n", username) logger.Debugf("user %q logged in.\n", username)
logger.Errorf("user %q logged in.\n", username) logger.Errorf("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "61" {
logger.Fatalf("user %q logged in.\n", username) logger.Fatalf("user %q logged in.\n", username)
} }
logger.Infof("user %q logged in.\n", username) logger.Infof("user %q logged in.\n", username)
logger.Logf(0, "user %q logged in.\n", username) logger.Logf(0, "user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "62" {
logger.Panicf("user %q logged in.\n", username) logger.Panicf("user %q logged in.\n", username)
} }
logger.Printf("user %q logged in.\n", username) logger.Printf("user %q logged in.\n", username)
@@ -603,11 +707,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
sLogger.DPanicf("user %q logged in.\n", username) sLogger.DPanicf("user %q logged in.\n", username)
sLogger.Debugf("user %q logged in.\n", username) sLogger.Debugf("user %q logged in.\n", username)
sLogger.Errorf("user %q logged in.\n", username) sLogger.Errorf("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "63" {
sLogger.Fatalf("user %q logged in.\n", username) sLogger.Fatalf("user %q logged in.\n", username)
} }
sLogger.Infof("user %q logged in.\n", username) sLogger.Infof("user %q logged in.\n", username)
if testFlag == " true" { if testFlag == "64" {
sLogger.Panicf("user %q logged in.\n", username) sLogger.Panicf("user %q logged in.\n", username)
} }
sLogger.Warnf("user %q logged in.\n", username) sLogger.Warnf("user %q logged in.\n", username)
@@ -620,10 +724,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
verbose.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" verbose.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
klog.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" klog.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
klog.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username" klog.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "65" {
klog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username" klog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
if testFlag == " true" { if testFlag == "66" {
klog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username" klog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
} }
@@ -639,10 +743,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
glog.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" glog.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
glog.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username" glog.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "67" {
glog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username" glog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
if testFlag == " true" { if testFlag == "68" {
glog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username" glog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
} }
@@ -650,11 +754,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
{ {
logrus.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logrus.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
logrus.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logrus.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "69" {
logrus.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logrus.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
logrus.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" logrus.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "70" {
logrus.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logrus.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
logrus.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logrus.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
@@ -666,12 +770,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
entry := logrus.WithFields(fields) entry := logrus.WithFields(fields)
entry.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
entry.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "71" {
entry.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
entry.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
entry.Logf(0, "user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Logf(0, "user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "72" {
entry.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
entry.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username" entry.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
@@ -682,12 +786,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
logger := entry.Logger logger := entry.Logger
logger.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
logger.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "73" {
logger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
logger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
logger.Logf(0, "user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Logf(0, "user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "74" {
logger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
logger.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username" logger.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
@@ -708,11 +812,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
sLogger.DPanicf("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.DPanicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
sLogger.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
sLogger.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "75" {
sLogger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
sLogger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" { if testFlag == "76" {
sLogger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
} }
sLogger.Warnf("user %#q logged in.\n", username) // $ hasTaintFlow="username" sLogger.Warnf("user %#q logged in.\n", username) // $ hasTaintFlow="username"

View File

@@ -37,22 +37,22 @@
| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password | | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password |
| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword | | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword |
| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword | | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword |
| passwords.go:32:12:32:19 | password | passwords.go:21:2:21:9 | definition of password | passwords.go:32:12:32:19 | password | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:33:13:33:20 | password | passwords.go:21:2:21:9 | definition of password | passwords.go:33:13:33:20 | password | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:34:14:34:35 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:34:14:34:35 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:36:14:36:35 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:36:14:36:35 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x | passwords.go:39:14:39:17 | obj1 | $@ flows to a logging call. | passwords.go:37:13:37:13 | x | Sensitive data returned by an access to password | | passwords.go:41:14:41:17 | obj1 | passwords.go:39:13:39:13 | x | passwords.go:41:14:41:17 | obj1 | $@ flows to a logging call. | passwords.go:39:13:39:13 | x | Sensitive data returned by an access to password |
| passwords.go:44:14:44:17 | obj2 | passwords.go:21:2:21:9 | definition of password | passwords.go:44:14:44:17 | obj2 | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:46:14:46:17 | obj2 | passwords.go:21:2:21:9 | definition of password | passwords.go:46:14:46:17 | obj2 | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:51:14:51:27 | fixed_password | passwords.go:50:2:50:15 | definition of fixed_password | passwords.go:51:14:51:27 | fixed_password | $@ flows to a logging call. | passwords.go:50:2:50:15 | definition of fixed_password | Sensitive data returned by an access to fixed_password | | passwords.go:53:14:53:27 | fixed_password | passwords.go:52:2:52:15 | definition of fixed_password | passwords.go:53:14:53:27 | fixed_password | $@ flows to a logging call. | passwords.go:52:2:52:15 | definition of fixed_password | Sensitive data returned by an access to fixed_password |
| passwords.go:89:14:89:26 | utilityObject | passwords.go:87:16:87:36 | call to make | passwords.go:89:14:89:26 | utilityObject | $@ flows to a logging call. | passwords.go:87:16:87:36 | call to make | Sensitive data returned by an access to passwordSet | | passwords.go:91:14:91:26 | utilityObject | passwords.go:89:16:89:36 | call to make | passwords.go:91:14:91:26 | utilityObject | $@ flows to a logging call. | passwords.go:89:16:89:36 | call to make | Sensitive data returned by an access to passwordSet |
| passwords.go:92:23:92:28 | secret | passwords.go:21:2:21:9 | definition of password | passwords.go:92:23:92:28 | secret | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:94:23:94:28 | secret | passwords.go:21:2:21:9 | definition of password | passwords.go:94:23:94:28 | secret | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:102:15:102:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:102:15:102:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:104:15:104:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:104:15:104:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:108:16:108:41 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:108:16:108:41 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:110:16:110:41 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:110:16:110:41 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:113:15:113:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:113:15:113:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:115:15:115:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:115:15:115:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:117:14:117:45 | ...+... | passwords.go:116:6:116:14 | definition of password1 | passwords.go:117:14:117:45 | ...+... | $@ flows to a logging call. | passwords.go:116:6:116:14 | definition of password1 | Sensitive data returned by an access to password1 | | passwords.go:119:14:119:45 | ...+... | passwords.go:118:6:118:14 | definition of password1 | passwords.go:119:14:119:45 | ...+... | $@ flows to a logging call. | passwords.go:118:6:118:14 | definition of password1 | Sensitive data returned by an access to password1 |
| passwords.go:127:14:127:19 | config | passwords.go:21:2:21:9 | definition of password | passwords.go:127:14:127:19 | config | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:129:14:129:19 | config | passwords.go:21:2:21:9 | definition of password | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:127:14:127:19 | config | passwords.go:121:13:121:14 | x3 | passwords.go:127:14:127:19 | config | $@ flows to a logging call. | passwords.go:121:13:121:14 | x3 | Sensitive data returned by an access to password | | passwords.go:129:14:129:19 | config | passwords.go:123:13:123:14 | x3 | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:123:13:123:14 | x3 | Sensitive data returned by an access to password |
| passwords.go:127:14:127:19 | config | passwords.go:124:13:124:25 | call to getPassword | passwords.go:127:14:127:19 | config | $@ flows to a logging call. | passwords.go:124:13:124:25 | call to getPassword | Sensitive data returned by a call to getPassword | | passwords.go:129:14:129:19 | config | passwords.go:126:13:126:25 | call to getPassword | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
| passwords.go:128:14:128:21 | selection of x | passwords.go:21:2:21:9 | definition of password | passwords.go:128:14:128:21 | selection of x | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password | | passwords.go:130:14:130:21 | selection of x | passwords.go:21:2:21:9 | definition of password | passwords.go:130:14:130:21 | selection of x | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
| passwords.go:129:14:129:21 | selection of y | passwords.go:124:13:124:25 | call to getPassword | passwords.go:129:14:129:21 | selection of y | $@ flows to a logging call. | passwords.go:124:13:124:25 | call to getPassword | Sensitive data returned by a call to getPassword | | passwords.go:131:14:131:21 | selection of y | passwords.go:126:13:126:25 | call to getPassword | passwords.go:131:14:131:21 | selection of y | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:9:2:9:9 | definition of password | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:9:2:9:9 | definition of password | Sensitive data returned by an access to password | | protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:9:2:9:9 | definition of password | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:9:2:9:9 | definition of password | Sensitive data returned by an access to password |
edges edges
| klog.go:21:3:26:3 | range statement[1] | klog.go:22:27:22:33 | headers | provenance | | | klog.go:21:3:26:3 | range statement[1] | klog.go:22:27:22:33 | headers | provenance | |
@@ -82,95 +82,15 @@ edges
| main.go:53:11:53:18 | password | main.go:54:12:54:19 | password | provenance | | | main.go:53:11:53:18 | password | main.go:54:12:54:19 | password | provenance | |
| main.go:53:11:53:18 | password | main.go:54:12:54:19 | password | provenance | | | main.go:53:11:53:18 | password | main.go:54:12:54:19 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:56:11:56:18 | password | provenance | | | main.go:54:12:54:19 | password | main.go:56:11:56:18 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:56:11:56:18 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:59:18:59:25 | password | provenance | | | main.go:54:12:54:19 | password | main.go:59:18:59:25 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:59:18:59:25 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:62:12:62:19 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 | | main.go:54:12:54:19 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 |
| main.go:54:12:54:19 | password | main.go:65:13:65:20 | password | provenance | | | main.go:54:12:54:19 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:68:11:68:18 | password | provenance | | | main.go:54:12:54:19 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:71:18:71:25 | password | provenance | | | main.go:54:12:54:19 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 | | main.go:54:12:54:19 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:54:12:54:19 | password | main.go:77:13:77:20 | password | provenance | | | main.go:54:12:54:19 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:54:12:54:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 | | main.go:54:12:54:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:54:12:54:19 | password | main.go:80:17:80:24 | password | provenance | | | main.go:54:12:54:19 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:59:18:59:25 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:59:18:59:25 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:62:12:62:19 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 |
| main.go:56:11:56:18 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:56:11:56:18 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:56:11:56:18 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:56:11:56:18 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:62:12:62:19 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 |
| main.go:59:18:59:25 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:59:18:59:25 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:59:18:59:25 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:59:18:59:25 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:65:13:65:20 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:62:12:62:19 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:62:12:62:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:62:12:62:19 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:68:11:68:18 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:65:13:65:20 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:65:13:65:20 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:65:13:65:20 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:68:11:68:18 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:68:11:68:18 | password | main.go:71:18:71:25 | password | provenance | |
| main.go:68:11:68:18 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:68:11:68:18 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:68:11:68:18 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:68:11:68:18 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:68:11:68:18 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:68:11:68:18 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:71:18:71:25 | password | main.go:74:12:74:19 | password | provenance | |
| main.go:71:18:71:25 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
| main.go:71:18:71:25 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:71:18:71:25 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:71:18:71:25 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:71:18:71:25 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:74:12:74:19 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:74:12:74:19 | password | main.go:77:13:77:20 | password | provenance | |
| main.go:74:12:74:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:74:12:74:19 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:77:13:77:20 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
| main.go:77:13:77:20 | password | main.go:80:17:80:24 | password | provenance | |
| main.go:80:17:80:24 | password | main.go:82:12:82:19 | password | provenance | | | main.go:80:17:80:24 | password | main.go:82:12:82:19 | password | provenance | |
| main.go:80:17:80:24 | password | main.go:83:17:83:24 | password | provenance | | | main.go:80:17:80:24 | password | main.go:83:17:83:24 | password | provenance | |
| main.go:80:17:80:24 | password | main.go:86:19:86:26 | password | provenance | | | main.go:80:17:80:24 | password | main.go:86:19:86:26 | password | provenance | |
@@ -182,46 +102,46 @@ edges
| passwords.go:8:12:8:12 | definition of x | passwords.go:9:14:9:14 | x | provenance | | | passwords.go:8:12:8:12 | definition of x | passwords.go:9:14:9:14 | x | provenance | |
| passwords.go:21:2:21:9 | definition of password | passwords.go:25:14:25:21 | password | provenance | | | passwords.go:21:2:21:9 | definition of password | passwords.go:25:14:25:21 | password | provenance | |
| passwords.go:21:2:21:9 | definition of password | passwords.go:30:8:30:15 | password | provenance | | | passwords.go:21:2:21:9 | definition of password | passwords.go:30:8:30:15 | password | provenance | |
| passwords.go:21:2:21:9 | definition of password | passwords.go:32:12:32:19 | password | provenance | | | passwords.go:21:2:21:9 | definition of password | passwords.go:33:13:33:20 | password | provenance | |
| passwords.go:21:2:21:9 | definition of password | passwords.go:34:28:34:35 | password | provenance | | | passwords.go:21:2:21:9 | definition of password | passwords.go:36:28:36:35 | password | provenance | |
| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x | provenance | | | passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x | provenance | |
| passwords.go:34:28:34:35 | password | passwords.go:34:14:34:35 | ...+... | provenance | Config | | passwords.go:36:28:36:35 | password | passwords.go:36:14:36:35 | ...+... | provenance | Config |
| passwords.go:34:28:34:35 | password | passwords.go:42:6:42:13 | password | provenance | | | passwords.go:36:28:36:35 | password | passwords.go:44:6:44:13 | password | provenance | |
| passwords.go:36:10:38:2 | struct literal | passwords.go:39:14:39:17 | obj1 | provenance | | | passwords.go:38:10:40:2 | struct literal | passwords.go:41:14:41:17 | obj1 | provenance | |
| passwords.go:37:13:37:13 | x | passwords.go:36:10:38:2 | struct literal | provenance | Config | | passwords.go:39:13:39:13 | x | passwords.go:38:10:40:2 | struct literal | provenance | Config |
| passwords.go:41:10:43:2 | struct literal | passwords.go:44:14:44:17 | obj2 | provenance | | | passwords.go:43:10:45:2 | struct literal | passwords.go:46:14:46:17 | obj2 | provenance | |
| passwords.go:42:6:42:13 | password | passwords.go:41:10:43:2 | struct literal | provenance | Config | | passwords.go:44:6:44:13 | password | passwords.go:43:10:45:2 | struct literal | provenance | Config |
| passwords.go:42:6:42:13 | password | passwords.go:48:11:48:18 | password | provenance | | | passwords.go:44:6:44:13 | password | passwords.go:50:11:50:18 | password | provenance | |
| passwords.go:48:11:48:18 | password | passwords.go:92:23:92:28 | secret | provenance | | | passwords.go:50:11:50:18 | password | passwords.go:94:23:94:28 | secret | provenance | |
| passwords.go:48:11:48:18 | password | passwords.go:102:33:102:40 | password | provenance | | | passwords.go:50:11:50:18 | password | passwords.go:104:33:104:40 | password | provenance | |
| passwords.go:48:11:48:18 | password | passwords.go:108:34:108:41 | password | provenance | | | passwords.go:50:11:50:18 | password | passwords.go:110:34:110:41 | password | provenance | |
| passwords.go:48:11:48:18 | password | passwords.go:113:33:113:40 | password | provenance | | | passwords.go:50:11:50:18 | password | passwords.go:115:33:115:40 | password | provenance | |
| passwords.go:48:11:48:18 | password | passwords.go:123:13:123:20 | password | provenance | | | passwords.go:50:11:50:18 | password | passwords.go:125:13:125:20 | password | provenance | |
| passwords.go:50:2:50:15 | definition of fixed_password | passwords.go:51:14:51:27 | fixed_password | provenance | | | passwords.go:52:2:52:15 | definition of fixed_password | passwords.go:53:14:53:27 | fixed_password | provenance | |
| passwords.go:86:19:88:2 | struct literal | passwords.go:89:14:89:26 | utilityObject | provenance | | | passwords.go:88:19:90:2 | struct literal | passwords.go:91:14:91:26 | utilityObject | provenance | |
| passwords.go:87:16:87:36 | call to make | passwords.go:86:19:88:2 | struct literal | provenance | Config | | passwords.go:89:16:89:36 | call to make | passwords.go:88:19:90:2 | struct literal | provenance | Config |
| passwords.go:102:33:102:40 | password | passwords.go:102:15:102:40 | ...+... | provenance | Config | | passwords.go:104:33:104:40 | password | passwords.go:104:15:104:40 | ...+... | provenance | Config |
| passwords.go:102:33:102:40 | password | passwords.go:108:34:108:41 | password | provenance | | | passwords.go:104:33:104:40 | password | passwords.go:110:34:110:41 | password | provenance | |
| passwords.go:102:33:102:40 | password | passwords.go:113:33:113:40 | password | provenance | | | passwords.go:104:33:104:40 | password | passwords.go:115:33:115:40 | password | provenance | |
| passwords.go:102:33:102:40 | password | passwords.go:123:13:123:20 | password | provenance | | | passwords.go:104:33:104:40 | password | passwords.go:125:13:125:20 | password | provenance | |
| passwords.go:108:34:108:41 | password | passwords.go:108:16:108:41 | ...+... | provenance | Config | | passwords.go:110:34:110:41 | password | passwords.go:110:16:110:41 | ...+... | provenance | Config |
| passwords.go:108:34:108:41 | password | passwords.go:113:33:113:40 | password | provenance | | | passwords.go:110:34:110:41 | password | passwords.go:115:33:115:40 | password | provenance | |
| passwords.go:108:34:108:41 | password | passwords.go:123:13:123:20 | password | provenance | | | passwords.go:110:34:110:41 | password | passwords.go:125:13:125:20 | password | provenance | |
| passwords.go:113:33:113:40 | password | passwords.go:113:15:113:40 | ...+... | provenance | Config | | passwords.go:115:33:115:40 | password | passwords.go:115:15:115:40 | ...+... | provenance | Config |
| passwords.go:113:33:113:40 | password | passwords.go:123:13:123:20 | password | provenance | | | passwords.go:115:33:115:40 | password | passwords.go:125:13:125:20 | password | provenance | |
| passwords.go:116:6:116:14 | definition of password1 | passwords.go:117:28:117:36 | password1 | provenance | | | passwords.go:118:6:118:14 | definition of password1 | passwords.go:119:28:119:36 | password1 | provenance | |
| passwords.go:117:28:117:36 | password1 | passwords.go:117:28:117:45 | call to String | provenance | Config | | passwords.go:119:28:119:36 | password1 | passwords.go:119:28:119:45 | call to String | provenance | Config |
| passwords.go:117:28:117:45 | call to String | passwords.go:117:14:117:45 | ...+... | provenance | Config | | passwords.go:119:28:119:45 | call to String | passwords.go:119:14:119:45 | ...+... | provenance | Config |
| passwords.go:120:12:125:2 | struct literal | passwords.go:127:14:127:19 | config | provenance | | | passwords.go:122:12:127:2 | struct literal | passwords.go:129:14:129:19 | config | provenance | |
| passwords.go:120:12:125:2 | struct literal [x] | passwords.go:128:14:128:19 | config [x] | provenance | | | passwords.go:122:12:127:2 | struct literal [x] | passwords.go:130:14:130:19 | config [x] | provenance | |
| passwords.go:120:12:125:2 | struct literal [y] | passwords.go:129:14:129:19 | config [y] | provenance | | | passwords.go:122:12:127:2 | struct literal [y] | passwords.go:131:14:131:19 | config [y] | provenance | |
| passwords.go:121:13:121:14 | x3 | passwords.go:120:12:125:2 | struct literal | provenance | Config | | passwords.go:123:13:123:14 | x3 | passwords.go:122:12:127:2 | struct literal | provenance | Config |
| passwords.go:123:13:123:20 | password | passwords.go:120:12:125:2 | struct literal | provenance | Config | | passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal | provenance | Config |
| passwords.go:123:13:123:20 | password | passwords.go:120:12:125:2 | struct literal [x] | provenance | | | passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal [x] | provenance | |
| passwords.go:124:13:124:25 | call to getPassword | passwords.go:120:12:125:2 | struct literal | provenance | Config | | passwords.go:126:13:126:25 | call to getPassword | passwords.go:122:12:127:2 | struct literal | provenance | Config |
| passwords.go:124:13:124:25 | call to getPassword | passwords.go:120:12:125:2 | struct literal [y] | provenance | | | passwords.go:126:13:126:25 | call to getPassword | passwords.go:122:12:127:2 | struct literal [y] | provenance | |
| passwords.go:128:14:128:19 | config [x] | passwords.go:128:14:128:21 | selection of x | provenance | | | passwords.go:130:14:130:19 | config [x] | passwords.go:130:14:130:21 | selection of x | provenance | |
| passwords.go:129:14:129:19 | config [y] | passwords.go:129:14:129:21 | selection of y | provenance | | | passwords.go:131:14:131:19 | config [y] | passwords.go:131:14:131:21 | selection of y | provenance | |
| protobuf.go:9:2:9:9 | definition of password | protobuf.go:12:22:12:29 | password | provenance | | | protobuf.go:9:2:9:9 | definition of password | protobuf.go:12:22:12:29 | password | provenance | |
| protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | provenance | | | protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | provenance | |
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | protobuf.go:14:14:14:18 | query [pointer, Description] | provenance | | | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | protobuf.go:14:14:14:18 | query [pointer, Description] | provenance | |
@@ -274,20 +194,12 @@ nodes
| main.go:54:12:54:19 | password | semmle.label | password | | main.go:54:12:54:19 | password | semmle.label | password |
| main.go:54:12:54:19 | password | semmle.label | password | | main.go:54:12:54:19 | password | semmle.label | password |
| main.go:56:11:56:18 | password | semmle.label | password | | main.go:56:11:56:18 | password | semmle.label | password |
| main.go:56:11:56:18 | password | semmle.label | password |
| main.go:59:18:59:25 | password | semmle.label | password |
| main.go:59:18:59:25 | password | semmle.label | password | | main.go:59:18:59:25 | password | semmle.label | password |
| main.go:62:12:62:19 | password | semmle.label | password | | main.go:62:12:62:19 | password | semmle.label | password |
| main.go:62:12:62:19 | password | semmle.label | password |
| main.go:65:13:65:20 | password | semmle.label | password |
| main.go:65:13:65:20 | password | semmle.label | password | | main.go:65:13:65:20 | password | semmle.label | password |
| main.go:68:11:68:18 | password | semmle.label | password | | main.go:68:11:68:18 | password | semmle.label | password |
| main.go:68:11:68:18 | password | semmle.label | password |
| main.go:71:18:71:25 | password | semmle.label | password |
| main.go:71:18:71:25 | password | semmle.label | password | | main.go:71:18:71:25 | password | semmle.label | password |
| main.go:74:12:74:19 | password | semmle.label | password | | main.go:74:12:74:19 | password | semmle.label | password |
| main.go:74:12:74:19 | password | semmle.label | password |
| main.go:77:13:77:20 | password | semmle.label | password |
| main.go:77:13:77:20 | password | semmle.label | password | | main.go:77:13:77:20 | password | semmle.label | password |
| main.go:79:14:79:21 | password | semmle.label | password | | main.go:79:14:79:21 | password | semmle.label | password |
| main.go:80:17:80:24 | password | semmle.label | password | | main.go:80:17:80:24 | password | semmle.label | password |
@@ -308,43 +220,43 @@ nodes
| passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword | | passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword |
| passwords.go:28:14:28:28 | call to getPassword | semmle.label | call to getPassword | | passwords.go:28:14:28:28 | call to getPassword | semmle.label | call to getPassword |
| passwords.go:30:8:30:15 | password | semmle.label | password | | passwords.go:30:8:30:15 | password | semmle.label | password |
| passwords.go:32:12:32:19 | password | semmle.label | password | | passwords.go:33:13:33:20 | password | semmle.label | password |
| passwords.go:34:14:34:35 | ...+... | semmle.label | ...+... | | passwords.go:36:14:36:35 | ...+... | semmle.label | ...+... |
| passwords.go:34:28:34:35 | password | semmle.label | password | | passwords.go:36:28:36:35 | password | semmle.label | password |
| passwords.go:36:10:38:2 | struct literal | semmle.label | struct literal | | passwords.go:38:10:40:2 | struct literal | semmle.label | struct literal |
| passwords.go:37:13:37:13 | x | semmle.label | x | | passwords.go:39:13:39:13 | x | semmle.label | x |
| passwords.go:39:14:39:17 | obj1 | semmle.label | obj1 | | passwords.go:41:14:41:17 | obj1 | semmle.label | obj1 |
| passwords.go:41:10:43:2 | struct literal | semmle.label | struct literal | | passwords.go:43:10:45:2 | struct literal | semmle.label | struct literal |
| passwords.go:42:6:42:13 | password | semmle.label | password | | passwords.go:44:6:44:13 | password | semmle.label | password |
| passwords.go:44:14:44:17 | obj2 | semmle.label | obj2 | | passwords.go:46:14:46:17 | obj2 | semmle.label | obj2 |
| passwords.go:48:11:48:18 | password | semmle.label | password | | passwords.go:50:11:50:18 | password | semmle.label | password |
| passwords.go:50:2:50:15 | definition of fixed_password | semmle.label | definition of fixed_password | | passwords.go:52:2:52:15 | definition of fixed_password | semmle.label | definition of fixed_password |
| passwords.go:51:14:51:27 | fixed_password | semmle.label | fixed_password | | passwords.go:53:14:53:27 | fixed_password | semmle.label | fixed_password |
| passwords.go:86:19:88:2 | struct literal | semmle.label | struct literal | | passwords.go:88:19:90:2 | struct literal | semmle.label | struct literal |
| passwords.go:87:16:87:36 | call to make | semmle.label | call to make | | passwords.go:89:16:89:36 | call to make | semmle.label | call to make |
| passwords.go:89:14:89:26 | utilityObject | semmle.label | utilityObject | | passwords.go:91:14:91:26 | utilityObject | semmle.label | utilityObject |
| passwords.go:92:23:92:28 | secret | semmle.label | secret | | passwords.go:94:23:94:28 | secret | semmle.label | secret |
| passwords.go:102:15:102:40 | ...+... | semmle.label | ...+... | | passwords.go:104:15:104:40 | ...+... | semmle.label | ...+... |
| passwords.go:102:33:102:40 | password | semmle.label | password | | passwords.go:104:33:104:40 | password | semmle.label | password |
| passwords.go:108:16:108:41 | ...+... | semmle.label | ...+... | | passwords.go:110:16:110:41 | ...+... | semmle.label | ...+... |
| passwords.go:108:34:108:41 | password | semmle.label | password | | passwords.go:110:34:110:41 | password | semmle.label | password |
| passwords.go:113:15:113:40 | ...+... | semmle.label | ...+... | | passwords.go:115:15:115:40 | ...+... | semmle.label | ...+... |
| passwords.go:113:33:113:40 | password | semmle.label | password | | passwords.go:115:33:115:40 | password | semmle.label | password |
| passwords.go:116:6:116:14 | definition of password1 | semmle.label | definition of password1 | | passwords.go:118:6:118:14 | definition of password1 | semmle.label | definition of password1 |
| passwords.go:117:14:117:45 | ...+... | semmle.label | ...+... | | passwords.go:119:14:119:45 | ...+... | semmle.label | ...+... |
| passwords.go:117:28:117:36 | password1 | semmle.label | password1 | | passwords.go:119:28:119:36 | password1 | semmle.label | password1 |
| passwords.go:117:28:117:45 | call to String | semmle.label | call to String | | passwords.go:119:28:119:45 | call to String | semmle.label | call to String |
| passwords.go:120:12:125:2 | struct literal | semmle.label | struct literal | | passwords.go:122:12:127:2 | struct literal | semmle.label | struct literal |
| passwords.go:120:12:125:2 | struct literal [x] | semmle.label | struct literal [x] | | passwords.go:122:12:127:2 | struct literal [x] | semmle.label | struct literal [x] |
| passwords.go:120:12:125:2 | struct literal [y] | semmle.label | struct literal [y] | | passwords.go:122:12:127:2 | struct literal [y] | semmle.label | struct literal [y] |
| passwords.go:121:13:121:14 | x3 | semmle.label | x3 | | passwords.go:123:13:123:14 | x3 | semmle.label | x3 |
| passwords.go:123:13:123:20 | password | semmle.label | password | | passwords.go:125:13:125:20 | password | semmle.label | password |
| passwords.go:124:13:124:25 | call to getPassword | semmle.label | call to getPassword | | passwords.go:126:13:126:25 | call to getPassword | semmle.label | call to getPassword |
| passwords.go:127:14:127:19 | config | semmle.label | config | | passwords.go:129:14:129:19 | config | semmle.label | config |
| passwords.go:128:14:128:19 | config [x] | semmle.label | config [x] | | passwords.go:130:14:130:19 | config [x] | semmle.label | config [x] |
| passwords.go:128:14:128:21 | selection of x | semmle.label | selection of x | | passwords.go:130:14:130:21 | selection of x | semmle.label | selection of x |
| passwords.go:129:14:129:19 | config [y] | semmle.label | config [y] | | passwords.go:131:14:131:19 | config [y] | semmle.label | config [y] |
| passwords.go:129:14:129:21 | selection of y | semmle.label | selection of y | | passwords.go:131:14:131:21 | selection of y | semmle.label | selection of y |
| protobuf.go:9:2:9:9 | definition of password | semmle.label | definition of password | | protobuf.go:9:2:9:9 | definition of password | semmle.label | definition of password |
| protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | semmle.label | implicit dereference [postupdate] [Description] | | protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | semmle.label | implicit dereference [postupdate] [Description] |
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | semmle.label | query [postupdate] [pointer, Description] | | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | semmle.label | query [postupdate] [pointer, Description] |

View File

@@ -16,7 +16,7 @@ func redact(kind, value string) string {
return value return value
} }
func test() { func test(selector int) {
name := "user" name := "user"
password := "P@ssw0rd" // $ Source password := "P@ssw0rd" // $ Source
x := "horsebatterystapleincorrect" x := "horsebatterystapleincorrect"
@@ -29,7 +29,9 @@ func test() {
myLog(password) myLog(password)
log.Panic(password) // $ Alert if selector == 1 {
log.Panic(password) // $ Alert
}
log.Println(name + ", " + password) // $ Alert log.Println(name + ", " + password) // $ Alert

View File

@@ -53,6 +53,9 @@ _extractor_name_prefix = "%s-%s" % (
"embeddable" if _for_embeddable else "standalone", "embeddable" if _for_embeddable else "standalone",
) )
_compiler_plugin_registrar_service_source = "src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar"
_compiler_plugin_registrar_service_target = "META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar"
py_binary( py_binary(
name = "generate_dbscheme", name = "generate_dbscheme",
srcs = ["generate_dbscheme.py"], srcs = ["generate_dbscheme.py"],
@@ -64,8 +67,14 @@ _resources = [
r[len("src/main/resources/"):], r[len("src/main/resources/"):],
) )
for r in glob(["src/main/resources/**"]) for r in glob(["src/main/resources/**"])
if r != _compiler_plugin_registrar_service_source
] ]
_compiler_plugin_registrar_service = (
_compiler_plugin_registrar_service_source,
_compiler_plugin_registrar_service_target,
)
kt_javac_options( kt_javac_options(
name = "javac-options", name = "javac-options",
release = "8", release = "8",
@@ -91,19 +100,32 @@ kt_javac_options(
# * `resource_strip_prefix` is unique per jar, so we must also put other resources under the same version prefix # * `resource_strip_prefix` is unique per jar, so we must also put other resources under the same version prefix
genrule( genrule(
name = "resources-%s" % v, name = "resources-%s" % v,
srcs = [src for src, _ in _resources], srcs = [src for src, _ in _resources] + (
[_compiler_plugin_registrar_service[0]] if not version_less(v, "2.4.0") else []
),
outs = [ outs = [
"%s/com/github/codeql/extractor.name" % v, "%s/com/github/codeql/extractor.name" % v,
] + [ ] + [
"%s/%s" % (v, target) "%s/%s" % (v, target)
for _, target in _resources for _, target in _resources
], ] + (
["%s/%s" % (
v,
_compiler_plugin_registrar_service[1],
)] if not version_less(v, "2.4.0") else []
),
cmd = "\n".join([ cmd = "\n".join([
"echo %s-%s > $(RULEDIR)/%s/com/github/codeql/extractor.name" % (_extractor_name_prefix, v, v), "echo %s-%s > $(RULEDIR)/%s/com/github/codeql/extractor.name" % (_extractor_name_prefix, v, v),
] + [ ] + [
"cp $(execpath %s) $(RULEDIR)/%s/%s" % (source, v, target) "cp $(execpath %s) $(RULEDIR)/%s/%s" % (source, v, target)
for source, target in _resources for source, target in _resources
]), ] + (
["cp $(execpath %s) $(RULEDIR)/%s/%s" % (
_compiler_plugin_registrar_service[0],
v,
_compiler_plugin_registrar_service[1],
)] if not version_less(v, "2.4.0") else []
)),
), ),
kt_jvm_library( kt_jvm_library(
name = "%s-%s" % (_extractor_name_prefix, v), name = "%s-%s" % (_extractor_name_prefix, v),

BIN
java/kotlin-extractor/deps/kotlin-compiler-2.4.0.jar (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
java/kotlin-extractor/deps/kotlin-stdlib-2.4.0.jar (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -27,7 +27,7 @@ import shutil
import io import io
import os import os
DEFAULT_VERSION = "2.3.20" DEFAULT_VERSION = "2.4.0"
def options(): def options():

View File

@@ -3,32 +3,21 @@
package com.github.codeql package com.github.codeql
import com.intellij.mock.MockProject
import com.intellij.openapi.extensions.LoadingOrder
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
class KotlinExtractorComponentRegistrar : Kotlin2ComponentRegistrar() { class KotlinExtractorComponentRegistrar : Kotlin2ComponentRegistrar() {
override fun registerProjectComponents( override fun doRegisterExtensions(configuration: CompilerConfiguration) {
project: MockProject,
configuration: CompilerConfiguration
) {
val invocationTrapFile = configuration[KEY_INVOCATION_TRAP_FILE] val invocationTrapFile = configuration[KEY_INVOCATION_TRAP_FILE]
if (invocationTrapFile == null) { if (invocationTrapFile == null) {
throw Exception("Required argument for TRAP invocation file not given") throw Exception("Required argument for TRAP invocation file not given")
} }
// Register with LoadingOrder.LAST to ensure the extractor runs after other registerExtractorExtension(
// IR generation plugins (like kotlinx.serialization) have generated their code.
val extensionPoint = project.extensionArea.getExtensionPoint(IrGenerationExtension.extensionPointName)
extensionPoint.registerExtension(
KotlinExtractorExtension( KotlinExtractorExtension(
invocationTrapFile, invocationTrapFile,
configuration[KEY_CHECK_TRAP_IDENTICAL] ?: false, configuration[KEY_CHECK_TRAP_IDENTICAL] ?: false,
configuration[KEY_COMPILATION_STARTTIME], configuration[KEY_COMPILATION_STARTTIME],
configuration[KEY_EXIT_AFTER_EXTRACTION] ?: false configuration[KEY_EXIT_AFTER_EXTRACTION] ?: false
), )
LoadingOrder.LAST,
project
) )
} }
} }

View File

@@ -173,9 +173,9 @@ open class KotlinFileExtractor(
when (d) { when (d) {
is IrFunction -> is IrFunction ->
when (d.name.asString()) { when (d.name.asString()) {
"toString" -> d.valueParameters.isEmpty() "toString" -> d.codeQlValueParameters.isEmpty()
"hashCode" -> d.valueParameters.isEmpty() "hashCode" -> d.codeQlValueParameters.isEmpty()
"equals" -> d.valueParameters.singleOrNull()?.type?.isNullableAny() ?: false "equals" -> d.codeQlValueParameters.singleOrNull()?.type?.isNullableAny() ?: false
else -> false else -> false
} && isJavaBinaryDeclaration(d) } && isJavaBinaryDeclaration(d)
else -> false else -> false
@@ -721,7 +721,7 @@ open class KotlinFileExtractor(
(it.type as? IrSimpleType)?.classFqName?.asString() != "kotlin.Deprecated" (it.type as? IrSimpleType)?.classFqName?.asString() != "kotlin.Deprecated"
} + } +
// Note we lose any arguments to @java.lang.Deprecated that were written in source. // Note we lose any arguments to @java.lang.Deprecated that were written in source.
IrConstructorCallImpl.fromSymbolOwner( codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
jldConstructor.returnType, jldConstructor.returnType,
@@ -781,13 +781,13 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(constructorCall) val locId = tw.getLocation(constructorCall)
tw.writeHasLocation(id, locId) tw.writeHasLocation(id, locId)
for (i in 0 until constructorCall.valueArgumentsCount) { for (i in 0 until constructorCall.codeQlValueArgumentsCount) {
val param = constructorCall.symbol.owner.valueParameters[i] val param = constructorCall.symbol.owner.codeQlValueParameters[i]
val prop = val prop =
constructorCall.symbol.owner.parentAsClass.declarations constructorCall.symbol.owner.parentAsClass.declarations
.filterIsInstance<IrProperty>() .filterIsInstance<IrProperty>()
.first { it.name == param.name } .first { it.name == param.name }
val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression val v = constructorCall.codeQlGetValueArgument(i) ?: param.defaultValue?.expression
val getter = prop.getter val getter = prop.getter
if (getter == null) { if (getter == null) {
logger.warnElement("Expected annotation property to define a getter", prop) logger.warnElement("Expected annotation property to define a getter", prop)
@@ -1115,9 +1115,9 @@ open class KotlinFileExtractor(
returnId, returnId,
0, 0,
returnId, returnId,
f.valueParameters.size, f.codeQlValueParameters.size,
{ argParent, idxOffset -> { argParent, idxOffset ->
f.valueParameters.forEachIndexed { idx, param -> f.codeQlValueParameters.forEachIndexed { idx, param ->
val syntheticParamId = useValueParameter(param, proxyFunctionId) val syntheticParamId = useValueParameter(param, proxyFunctionId)
extractVariableAccess( extractVariableAccess(
syntheticParamId, syntheticParamId,
@@ -1695,9 +1695,9 @@ open class KotlinFileExtractor(
returnId, returnId,
0, 0,
returnId, returnId,
f.valueParameters.size, f.codeQlValueParameters.size,
{ argParentId, idxOffset -> { argParentId, idxOffset ->
f.valueParameters.mapIndexed { idx, param -> f.codeQlValueParameters.mapIndexed { idx, param ->
val syntheticParamId = useValueParameter(param, functionId) val syntheticParamId = useValueParameter(param, functionId)
extractVariableAccess( extractVariableAccess(
syntheticParamId, syntheticParamId,
@@ -1792,7 +1792,7 @@ open class KotlinFileExtractor(
extractBody: Boolean, extractBody: Boolean,
extractMethodAndParameterTypeAccesses: Boolean extractMethodAndParameterTypeAccesses: Boolean
) { ) {
if (f.valueParameters.none { it.defaultValue != null }) return if (f.codeQlValueParameters.none { it.defaultValue != null }) return
val id = getDefaultsMethodLabel(f) val id = getDefaultsMethodLabel(f)
if (id == null) { if (id == null) {
@@ -1800,7 +1800,7 @@ open class KotlinFileExtractor(
return return
} }
val locId = getLocation(f, null) val locId = getLocation(f, null)
val extReceiver = f.extensionReceiverParameter val extReceiver = f.codeQlExtensionReceiverParameter
val dispatchReceiver = if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter val dispatchReceiver = if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter
val parameterTypes = getDefaultsMethodArgTypes(f) val parameterTypes = getDefaultsMethodArgTypes(f)
val allParamTypeResults = val allParamTypeResults =
@@ -1869,7 +1869,7 @@ open class KotlinFileExtractor(
tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_ARGUMENTS_METHOD.kind) tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_ARGUMENTS_METHOD.kind)
if (extractBody) { if (extractBody) {
val nonSyntheticParams = listOfNotNull(dispatchReceiver) + f.valueParameters val nonSyntheticParams = listOfNotNull(dispatchReceiver) + f.codeQlValueParameters
// This stack entry represents as if we're extracting the 'real' function `f`, giving // This stack entry represents as if we're extracting the 'real' function `f`, giving
// the indices of its non-synthetic parameters // the indices of its non-synthetic parameters
// such that when we extract the default expressions below, any reference to f's nth // such that when we extract the default expressions below, any reference to f's nth
@@ -1895,12 +1895,12 @@ open class KotlinFileExtractor(
val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2) val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2)
val intType = pluginContext.irBuiltIns.intType val intType = pluginContext.irBuiltIns.intType
val paramIdxOffset = val paramIdxOffset =
listOf(dispatchReceiver, f.extensionReceiverParameter).count { it != null } listOf(dispatchReceiver, f.codeQlExtensionReceiverParameter).count { it != null }
extractBlockBody(id, locId).also { blockId -> extractBlockBody(id, locId).also { blockId ->
var nextStmt = 0 var nextStmt = 0
// For each parameter with a default, sub in the default value if the caller // For each parameter with a default, sub in the default value if the caller
// hasn't supplied a value: // hasn't supplied a value:
f.valueParameters.forEachIndexed { paramIdx, param -> f.codeQlValueParameters.forEachIndexed { paramIdx, param ->
val defaultVal = param.defaultValue val defaultVal = param.defaultValue
if (defaultVal != null) { if (defaultVal != null) {
extractIfStmt(locId, blockId, nextStmt++, id).also { ifId -> extractIfStmt(locId, blockId, nextStmt++, id).also { ifId ->
@@ -1975,7 +1975,7 @@ open class KotlinFileExtractor(
id id
) )
tw.writeHasLocation(thisCallId, locId) tw.writeHasLocation(thisCallId, locId)
f.valueParameters.forEachIndexed { idx, param -> f.codeQlValueParameters.forEachIndexed { idx, param ->
extractVariableAccess( extractVariableAccess(
tw.getLabelFor<DbParam>(getValueParameterLabel(id, idx)), tw.getLabelFor<DbParam>(getValueParameterLabel(id, idx)),
param.type, param.type,
@@ -2003,9 +2003,9 @@ open class KotlinFileExtractor(
) )
.also { thisCallId -> .also { thisCallId ->
val realFnIdxOffset = val realFnIdxOffset =
if (f.extensionReceiverParameter != null) 1 else 0 if (f.codeQlExtensionReceiverParameter != null) 1 else 0
val paramMappings = val paramMappings =
f.valueParameters.mapIndexed { idx, param -> f.codeQlValueParameters.mapIndexed { idx, param ->
Triple( Triple(
param.type, param.type,
idx + paramIdxOffset, idx + paramIdxOffset,
@@ -2156,7 +2156,7 @@ open class KotlinFileExtractor(
val dispatchReceiver = val dispatchReceiver =
f.dispatchReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) } f.dispatchReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) }
val extensionReceiver = val extensionReceiver =
f.extensionReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) } f.codeQlExtensionReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) }
extractExpressionBody(overloadId, realFunctionLocId).also { returnId -> extractExpressionBody(overloadId, realFunctionLocId).also { returnId ->
extractsDefaultsCall( extractsDefaultsCall(
@@ -2180,28 +2180,28 @@ open class KotlinFileExtractor(
if (!f.hasAnnotation(jvmOverloadsFqName)) { if (!f.hasAnnotation(jvmOverloadsFqName)) {
if ( if (
f is IrConstructor && f is IrConstructor &&
f.valueParameters.isNotEmpty() && f.codeQlValueParameters.isNotEmpty() &&
f.valueParameters.all { it.defaultValue != null } && f.codeQlValueParameters.all { it.defaultValue != null } &&
f.parentClassOrNull?.let { f.parentClassOrNull?.let {
// Don't create a default constructor for an annotation class, or a class // Don't create a default constructor for an annotation class, or a class
// that explicitly declares a no-arg constructor. // that explicitly declares a no-arg constructor.
!it.isAnnotationClass && !it.isAnnotationClass &&
it.declarations.none { d -> it.declarations.none { d ->
d is IrConstructor && d.valueParameters.isEmpty() d is IrConstructor && d.codeQlValueParameters.isEmpty()
} }
} == true } == true
) { ) {
// Per https://kotlinlang.org/docs/classes.html#creating-instances-of-classes, a // Per https://kotlinlang.org/docs/classes.html#creating-instances-of-classes, a
// single default overload gets created specifically // single default overload gets created specifically
// when we have all default parameters, regardless of `@JvmOverloads`. // when we have all default parameters, regardless of `@JvmOverloads`.
extractGeneratedOverload(f.valueParameters.map { _ -> null }) extractGeneratedOverload(f.codeQlValueParameters.map { _ -> null })
} }
return return
} }
val paramList: MutableList<IrValueParameter?> = f.valueParameters.toMutableList() val paramList: MutableList<IrValueParameter?> = f.codeQlValueParameters.toMutableList()
for (n in (f.valueParameters.size - 1) downTo 0) { for (n in (f.codeQlValueParameters.size - 1) downTo 0) {
if (f.valueParameters[n].defaultValue != null) { if (f.codeQlValueParameters[n].defaultValue != null) {
paramList[n] = null // Remove this parameter, to be replaced by a default value paramList[n] = null // Remove this parameter, to be replaced by a default value
extractGeneratedOverload(paramList) extractGeneratedOverload(paramList)
} }
@@ -2327,7 +2327,7 @@ open class KotlinFileExtractor(
getClassByFqName(pluginContext, it)?.let { annotationClass -> getClassByFqName(pluginContext, it)?.let { annotationClass ->
annotationClass.owner.declarations.firstIsInstanceOrNull<IrConstructor>()?.let { annotationClass.owner.declarations.firstIsInstanceOrNull<IrConstructor>()?.let {
annotationConstructor -> annotationConstructor ->
IrConstructorCallImpl.fromSymbolOwner( codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
annotationConstructor.returnType, annotationConstructor.returnType,
@@ -2388,13 +2388,13 @@ open class KotlinFileExtractor(
id id
} }
val extReceiver = f.extensionReceiverParameter val extReceiver = f.codeQlExtensionReceiverParameter
// The following parameter order is correct, because member $default methods (where // The following parameter order is correct, because member $default methods (where
// the order would be [dispatchParam], [extensionParam], normalParams) are not // the order would be [dispatchParam], [extensionParam], normalParams) are not
// extracted here // extracted here
val fParameters = val fParameters =
listOfNotNull(extReceiver) + listOfNotNull(extReceiver) +
(overriddenAttributes?.valueParameters ?: f.valueParameters) (overriddenAttributes?.valueParameters ?: f.codeQlValueParameters)
val paramTypes = val paramTypes =
fParameters.mapIndexed { i, vp -> fParameters.mapIndexed { i, vp ->
extractValueParameter( extractValueParameter(
@@ -3069,14 +3069,14 @@ open class KotlinFileExtractor(
logger.errorElement("Unexpected dispatch receiver found", c) logger.errorElement("Unexpected dispatch receiver found", c)
} }
if (c.valueArgumentsCount < 1) { if (c.codeQlValueArgumentsCount < 1) {
logger.errorElement("No arguments found", c) logger.errorElement("No arguments found", c)
return return
} }
extractArgument(id, c, callable, enclosingStmt, 0, "Operand null") extractArgument(id, c, callable, enclosingStmt, 0, "Operand null")
if (c.valueArgumentsCount > 1) { if (c.codeQlValueArgumentsCount > 1) {
logger.errorElement("Extra arguments found", c) logger.errorElement("Extra arguments found", c)
} }
} }
@@ -3095,21 +3095,21 @@ open class KotlinFileExtractor(
logger.errorElement("Unexpected dispatch receiver found", c) logger.errorElement("Unexpected dispatch receiver found", c)
} }
if (c.valueArgumentsCount < 1) { if (c.codeQlValueArgumentsCount < 1) {
logger.errorElement("No arguments found", c) logger.errorElement("No arguments found", c)
return return
} }
extractArgument(id, c, callable, enclosingStmt, 0, "LHS null") extractArgument(id, c, callable, enclosingStmt, 0, "LHS null")
if (c.valueArgumentsCount < 2) { if (c.codeQlValueArgumentsCount < 2) {
logger.errorElement("No RHS found", c) logger.errorElement("No RHS found", c)
return return
} }
extractArgument(id, c, callable, enclosingStmt, 1, "RHS null") extractArgument(id, c, callable, enclosingStmt, 1, "RHS null")
if (c.valueArgumentsCount > 2) { if (c.codeQlValueArgumentsCount > 2) {
logger.errorElement("Extra arguments found", c) logger.errorElement("Extra arguments found", c)
} }
} }
@@ -3122,7 +3122,7 @@ open class KotlinFileExtractor(
idx: Int, idx: Int,
msg: String msg: String
) { ) {
val op = c.getValueArgument(idx) val op = c.codeQlGetValueArgument(idx)
if (op == null) { if (op == null) {
logger.errorElement(msg, c) logger.errorElement(msg, c)
} else { } else {
@@ -3267,8 +3267,8 @@ open class KotlinFileExtractor(
// and which should be replaced by defaults. The final Object parameter is apparently always // and which should be replaced by defaults. The final Object parameter is apparently always
// null. // null.
(listOfNotNull(if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter?.type) + (listOfNotNull(if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter?.type) +
listOfNotNull(f.extensionReceiverParameter?.type) + listOfNotNull(f.codeQlExtensionReceiverParameter?.type) +
f.valueParameters.map { it.type } + f.codeQlValueParameters.map { it.type } +
listOf(pluginContext.irBuiltIns.intType, getDefaultsMethodLastArgType(f))) listOf(pluginContext.irBuiltIns.intType, getDefaultsMethodLastArgType(f)))
.map { erase(it) } .map { erase(it) }
@@ -3345,7 +3345,7 @@ open class KotlinFileExtractor(
val overriddenCallTarget = val overriddenCallTarget =
(callTarget as? IrSimpleFunction)?.allOverridden(includeSelf = true)?.firstOrNull { (callTarget as? IrSimpleFunction)?.allOverridden(includeSelf = true)?.firstOrNull {
it.overriddenSymbols.isEmpty() && it.overriddenSymbols.isEmpty() &&
it.valueParameters.any { p -> p.defaultValue != null } it.codeQlValueParameters.any { p -> p.defaultValue != null }
} ?: callTarget } ?: callTarget
if (isExternalDeclaration(overriddenCallTarget)) { if (isExternalDeclaration(overriddenCallTarget)) {
// Likewise, ensure the overridden target gets extracted. // Likewise, ensure the overridden target gets extracted.
@@ -3419,7 +3419,7 @@ open class KotlinFileExtractor(
} }
val valueArgsWithDummies = val valueArgsWithDummies =
valueArguments.zip(callTarget.valueParameters).map { (expr, param) -> valueArguments.zip(callTarget.codeQlValueParameters).map { (expr, param) ->
expr ?: IrConstImpl.defaultValueForType(0, 0, param.type) expr ?: IrConstImpl.defaultValueForType(0, 0, param.type)
} }
@@ -3529,7 +3529,7 @@ open class KotlinFileExtractor(
callTarget: IrFunction, callTarget: IrFunction,
valueArguments: List<IrExpression?> valueArguments: List<IrExpression?>
): Boolean { ): Boolean {
val varargParam = callTarget.valueParameters.withIndex().find { it.value.isVararg } val varargParam = callTarget.codeQlValueParameters.withIndex().find { it.value.isVararg }
// If the vararg param is the only one not specified, and it has no default value, then we // If the vararg param is the only one not specified, and it has no default value, then we
// don't need to call a $default method, // don't need to call a $default method,
// as omitting it already implies passing an empty vararg array. // as omitting it already implies passing an empty vararg array.
@@ -3805,7 +3805,7 @@ open class KotlinFileExtractor(
) = ) =
extractCallValueArguments( extractCallValueArguments(
callId, callId,
(0 until call.valueArgumentsCount).map { call.getValueArgument(it) }, (0 until call.codeQlValueArgumentsCount).map { call.codeQlGetValueArgument(it) },
enclosingStmt, enclosingStmt,
enclosingCallable, enclosingCallable,
idxOffset idxOffset
@@ -3874,7 +3874,7 @@ open class KotlinFileExtractor(
(owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type || (owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type ||
(owner.parent is IrExternalPackageFragment && (owner.parent is IrExternalPackageFragment &&
getFileClassFqName(owner)?.asString() == type)) && getFileClassFqName(owner)?.asString() == type)) &&
owner.valueParameters owner.codeQlValueParameters
.map { it.type.classFqName?.asString() } .map { it.type.classFqName?.asString() }
.toTypedArray() contentEquals parameterTypes .toTypedArray() contentEquals parameterTypes
} }
@@ -3926,8 +3926,8 @@ open class KotlinFileExtractor(
val result = val result =
javaLangString?.declarations?.findSubType<IrFunction> { javaLangString?.declarations?.findSubType<IrFunction> {
it.name.asString() == "valueOf" && it.name.asString() == "valueOf" &&
it.valueParameters.size == 1 && it.codeQlValueParameters.size == 1 &&
it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType it.codeQlValueParameters[0].type == pluginContext.irBuiltIns.anyNType
} }
if (result == null) { if (result == null) {
logger.error("Couldn't find declaration java.lang.String.valueOf(Object)") logger.error("Couldn't find declaration java.lang.String.valueOf(Object)")
@@ -3951,7 +3951,7 @@ open class KotlinFileExtractor(
val kotlinNoWhenBranchMatchedConstructor by lazy { val kotlinNoWhenBranchMatchedConstructor by lazy {
val result = val result =
kotlinNoWhenBranchMatchedExn?.declarations?.findSubType<IrConstructor> { kotlinNoWhenBranchMatchedExn?.declarations?.findSubType<IrConstructor> {
it.valueParameters.isEmpty() it.codeQlValueParameters.isEmpty()
} }
if (result == null) { if (result == null) {
logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException") logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException")
@@ -3990,7 +3990,7 @@ open class KotlinFileExtractor(
verboseln("No match as function name is ${target.name.asString()} not $fName") verboseln("No match as function name is ${target.name.asString()} not $fName")
return false return false
} }
val extensionReceiverParameter = target.extensionReceiverParameter val extensionReceiverParameter = target.codeQlExtensionReceiverParameter
val targetClass = val targetClass =
if (extensionReceiverParameter == null) { if (extensionReceiverParameter == null) {
if (isNullable == true) { if (isNullable == true) {
@@ -4098,8 +4098,8 @@ open class KotlinFileExtractor(
) { ) {
val typeArgs = val typeArgs =
if (extractMethodTypeArguments) if (extractMethodTypeArguments)
(0 until c.typeArgumentsCount) (0 until c.codeQlTypeArgumentsCount)
.map { c.getTypeArgument(it) } .map { c.codeQlGetTypeArgument(it) }
.requireNoNullsOrNull() .requireNoNullsOrNull()
else listOf() else listOf()
@@ -4116,9 +4116,9 @@ open class KotlinFileExtractor(
parent, parent,
idx, idx,
enclosingStmt, enclosingStmt,
(0 until c.valueArgumentsCount).map { c.getValueArgument(it) }, (0 until c.codeQlValueArgumentsCount).map { c.codeQlGetValueArgument(it) },
c.dispatchReceiver, c.dispatchReceiver,
c.extensionReceiver, c.codeQlExtensionReceiver,
typeArgs, typeArgs,
extractClassTypeArguments, extractClassTypeArguments,
c.superQualifierSymbol c.superQualifierSymbol
@@ -4126,12 +4126,12 @@ open class KotlinFileExtractor(
} }
fun extractSpecialEnumFunction(fnName: String) { fun extractSpecialEnumFunction(fnName: String) {
if (c.typeArgumentsCount != 1) { if (c.codeQlTypeArgumentsCount != 1) {
logger.errorElement("Expected to find exactly one type argument", c) logger.errorElement("Expected to find exactly one type argument", c)
return return
} }
val enumType = (c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner val enumType = (c.codeQlGetTypeArgument(0) as? IrSimpleType)?.classifier?.owner
if (enumType == null) { if (enumType == null) {
logger.errorElement("Couldn't find type of enum type", c) logger.errorElement("Couldn't find type of enum type", c)
return return
@@ -4178,13 +4178,13 @@ open class KotlinFileExtractor(
} else { } else {
extractExpressionExpr(receiver, callable, id, 0, enclosingStmt) extractExpressionExpr(receiver, callable, id, 0, enclosingStmt)
} }
if (c.valueArgumentsCount < 1) { if (c.codeQlValueArgumentsCount < 1) {
logger.errorElement("No RHS found", c) logger.errorElement("No RHS found", c)
} else { } else {
if (c.valueArgumentsCount > 1) { if (c.codeQlValueArgumentsCount > 1) {
logger.errorElement("Extra arguments found", c) logger.errorElement("Extra arguments found", c)
} }
val arg = c.getValueArgument(0) val arg = c.codeQlGetValueArgument(0)
if (arg == null) { if (arg == null) {
logger.errorElement("RHS null", c) logger.errorElement("RHS null", c)
} else { } else {
@@ -4205,7 +4205,7 @@ open class KotlinFileExtractor(
} else { } else {
extractExpressionExpr(receiver, callable, id, 0, enclosingStmt) extractExpressionExpr(receiver, callable, id, 0, enclosingStmt)
} }
if (c.valueArgumentsCount > 0) { if (c.codeQlValueArgumentsCount > 0) {
logger.errorElement("Extra arguments found", c) logger.errorElement("Extra arguments found", c)
} }
} }
@@ -4219,7 +4219,7 @@ open class KotlinFileExtractor(
} }
fun binopExt(id: Label<out DbExpr>) { fun binopExt(id: Label<out DbExpr>) {
binopReceiver(id, c.extensionReceiver, "Extension receiver") binopReceiver(id, c.codeQlExtensionReceiver, "Extension receiver")
} }
fun unaryopDisp(id: Label<out DbExpr>) { fun unaryopDisp(id: Label<out DbExpr>) {
@@ -4227,7 +4227,7 @@ open class KotlinFileExtractor(
} }
fun unaryopExt(id: Label<out DbExpr>) { fun unaryopExt(id: Label<out DbExpr>) {
unaryopReceiver(id, c.extensionReceiver, "Extension receiver") unaryopReceiver(id, c.codeQlExtensionReceiver, "Extension receiver")
} }
val dr = c.dispatchReceiver val dr = c.dispatchReceiver
@@ -4249,7 +4249,7 @@ open class KotlinFileExtractor(
parent, parent,
idx, idx,
enclosingStmt, enclosingStmt,
listOf(c.extensionReceiver, c.getValueArgument(0)), listOf(c.codeQlExtensionReceiver, c.codeQlGetValueArgument(0)),
null, null,
null null
) )
@@ -4350,7 +4350,7 @@ open class KotlinFileExtractor(
// != gets desugared into not and ==. Here we resugar it. // != gets desugared into not and ==. Here we resugar it.
c.origin == IrStatementOrigin.EXCLEQ && c.origin == IrStatementOrigin.EXCLEQ &&
isFunction(target, "kotlin", "Boolean", "not") && isFunction(target, "kotlin", "Boolean", "not") &&
c.valueArgumentsCount == 0 && c.codeQlValueArgumentsCount == 0 &&
dr != null && dr != null &&
dr is IrCall && dr is IrCall &&
isBuiltinCallInternal(dr, "EQEQ") -> { isBuiltinCallInternal(dr, "EQEQ") -> {
@@ -4362,7 +4362,7 @@ open class KotlinFileExtractor(
} }
c.origin == IrStatementOrigin.EXCLEQEQ && c.origin == IrStatementOrigin.EXCLEQEQ &&
isFunction(target, "kotlin", "Boolean", "not") && isFunction(target, "kotlin", "Boolean", "not") &&
c.valueArgumentsCount == 0 && c.codeQlValueArgumentsCount == 0 &&
dr != null && dr != null &&
dr is IrCall && dr is IrCall &&
isBuiltinCallInternal(dr, "EQEQEQ") -> { isBuiltinCallInternal(dr, "EQEQEQ") -> {
@@ -4374,7 +4374,7 @@ open class KotlinFileExtractor(
} }
c.origin == IrStatementOrigin.EXCLEQ && c.origin == IrStatementOrigin.EXCLEQ &&
isFunction(target, "kotlin", "Boolean", "not") && isFunction(target, "kotlin", "Boolean", "not") &&
c.valueArgumentsCount == 0 && c.codeQlValueArgumentsCount == 0 &&
dr != null && dr != null &&
dr is IrCall && dr is IrCall &&
isBuiltinCallInternal(dr, "ieee754equals") -> { isBuiltinCallInternal(dr, "ieee754equals") -> {
@@ -4576,7 +4576,7 @@ open class KotlinFileExtractor(
parent, parent,
idx, idx,
enclosingStmt, enclosingStmt,
listOf(c.extensionReceiver), listOf(c.codeQlExtensionReceiver),
null, null,
null null
) )
@@ -4596,8 +4596,8 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(c) val locId = tw.getLocation(c)
extractExprContext(id, locId, callable, enclosingStmt) extractExprContext(id, locId, callable, enclosingStmt)
if (c.typeArgumentsCount == 1) { if (c.codeQlTypeArgumentsCount == 1) {
val typeArgument = c.getTypeArgument(0) val typeArgument = c.codeQlGetTypeArgument(0)
if (typeArgument == null) { if (typeArgument == null) {
logger.errorElement("Type argument missing in an arrayOfNulls call", c) logger.errorElement("Type argument missing in an arrayOfNulls call", c)
} else { } else {
@@ -4618,8 +4618,8 @@ open class KotlinFileExtractor(
) )
} }
if (c.valueArgumentsCount == 1) { if (c.codeQlValueArgumentsCount == 1) {
val dim = c.getValueArgument(0) val dim = c.codeQlGetValueArgument(0)
if (dim != null) { if (dim != null) {
extractExpressionExpr(dim, callable, id, 0, enclosingStmt) extractExpressionExpr(dim, callable, id, 0, enclosingStmt)
} else { } else {
@@ -4651,8 +4651,8 @@ open class KotlinFileExtractor(
c.type.getArrayElementTypeCodeQL(pluginContext.irBuiltIns) c.type.getArrayElementTypeCodeQL(pluginContext.irBuiltIns)
} else { } else {
// TODO: is there any reason not to always use getArrayElementTypeCodeQL? // TODO: is there any reason not to always use getArrayElementTypeCodeQL?
if (c.typeArgumentsCount == 1) { if (c.codeQlTypeArgumentsCount == 1) {
c.getTypeArgument(0).also { c.codeQlGetTypeArgument(0).also {
if (it == null) { if (it == null) {
logger.errorElement( logger.errorElement(
"Type argument missing in an arrayOf call", "Type argument missing in an arrayOf call",
@@ -4670,7 +4670,7 @@ open class KotlinFileExtractor(
} }
val arg = val arg =
if (c.valueArgumentsCount == 1) c.getValueArgument(0) if (c.codeQlValueArgumentsCount == 1) c.codeQlGetValueArgument(0)
else { else {
logger.errorElement( logger.errorElement(
"Expected to find only one (vararg) argument in ${c.symbol.owner.name.asString()} call", "Expected to find only one (vararg) argument in ${c.symbol.owner.name.asString()} call",
@@ -4719,7 +4719,7 @@ open class KotlinFileExtractor(
return return
} }
val ext = c.extensionReceiver val ext = c.codeQlExtensionReceiver
if (ext == null) { if (ext == null) {
logger.errorElement( logger.errorElement(
"No extension receiver found for `KClass::java` call", "No extension receiver found for `KClass::java` call",
@@ -4826,8 +4826,8 @@ open class KotlinFileExtractor(
c.origin == IrStatementOrigin.EQ && c.origin == IrStatementOrigin.EQ &&
c.dispatchReceiver != null -> { c.dispatchReceiver != null -> {
val array = c.dispatchReceiver val array = c.dispatchReceiver
val arrayIdx = c.getValueArgument(0) val arrayIdx = c.codeQlGetValueArgument(0)
val assignedValue = c.getValueArgument(1) val assignedValue = c.codeQlGetValueArgument(1)
if (array != null && arrayIdx != null && assignedValue != null) { if (array != null && arrayIdx != null && assignedValue != null) {
@@ -4882,22 +4882,22 @@ open class KotlinFileExtractor(
} }
isBuiltinCall(c, "<unsafe-coerce>", "kotlin.jvm.internal") -> { isBuiltinCall(c, "<unsafe-coerce>", "kotlin.jvm.internal") -> {
if (c.valueArgumentsCount != 1) { if (c.codeQlValueArgumentsCount != 1) {
logger.errorElement( logger.errorElement(
"Expected to find one argument for a kotlin.jvm.internal.<unsafe-coerce>() call, but found ${c.valueArgumentsCount}", "Expected to find one argument for a kotlin.jvm.internal.<unsafe-coerce>() call, but found ${c.codeQlValueArgumentsCount}",
c c
) )
return return
} }
if (c.typeArgumentsCount != 2) { if (c.codeQlTypeArgumentsCount != 2) {
logger.errorElement( logger.errorElement(
"Expected to find two type arguments for a kotlin.jvm.internal.<unsafe-coerce>() call, but found ${c.typeArgumentsCount}", "Expected to find two type arguments for a kotlin.jvm.internal.<unsafe-coerce>() call, but found ${c.codeQlTypeArgumentsCount}",
c c
) )
return return
} }
val valueArg = c.getValueArgument(0) val valueArg = c.codeQlGetValueArgument(0)
if (valueArg == null) { if (valueArg == null) {
logger.errorElement( logger.errorElement(
"Cannot find value argument for a kotlin.jvm.internal.<unsafe-coerce>() call", "Cannot find value argument for a kotlin.jvm.internal.<unsafe-coerce>() call",
@@ -4905,7 +4905,7 @@ open class KotlinFileExtractor(
) )
return return
} }
val typeArg = c.getTypeArgument(1) val typeArg = c.codeQlGetTypeArgument(1)
if (typeArg == null) { if (typeArg == null) {
logger.errorElement( logger.errorElement(
"Cannot find type argument for a kotlin.jvm.internal.<unsafe-coerce>() call", "Cannot find type argument for a kotlin.jvm.internal.<unsafe-coerce>() call",
@@ -4924,7 +4924,7 @@ open class KotlinFileExtractor(
extractExpressionExpr(valueArg, callable, id, 1, enclosingStmt) extractExpressionExpr(valueArg, callable, id, 1, enclosingStmt)
} }
isBuiltinCallInternal(c, "dataClassArrayMemberToString") -> { isBuiltinCallInternal(c, "dataClassArrayMemberToString") -> {
val arrayArg = c.getValueArgument(0) val arrayArg = c.codeQlGetValueArgument(0)
val realArrayClass = arrayArg?.type?.classOrNull val realArrayClass = arrayArg?.type?.classOrNull
if (realArrayClass == null) { if (realArrayClass == null) {
logger.errorElement( logger.errorElement(
@@ -4936,8 +4936,8 @@ open class KotlinFileExtractor(
val realCallee = val realCallee =
javaUtilArrays?.declarations?.findSubType<IrFunction> { decl -> javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
decl.name.asString() == "toString" && decl.name.asString() == "toString" &&
decl.valueParameters.size == 1 && decl.codeQlValueParameters.size == 1 &&
decl.valueParameters[0].type.classOrNull?.let { decl.codeQlValueParameters[0].type.classOrNull?.let {
it == realArrayClass it == realArrayClass
} == true } == true
} }
@@ -4962,7 +4962,7 @@ open class KotlinFileExtractor(
} }
} }
isBuiltinCallInternal(c, "dataClassArrayMemberHashCode") -> { isBuiltinCallInternal(c, "dataClassArrayMemberHashCode") -> {
val arrayArg = c.getValueArgument(0) val arrayArg = c.codeQlGetValueArgument(0)
val realArrayClass = arrayArg?.type?.classOrNull val realArrayClass = arrayArg?.type?.classOrNull
if (realArrayClass == null) { if (realArrayClass == null) {
logger.errorElement( logger.errorElement(
@@ -4974,8 +4974,8 @@ open class KotlinFileExtractor(
val realCallee = val realCallee =
javaUtilArrays?.declarations?.findSubType<IrFunction> { decl -> javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
decl.name.asString() == "hashCode" && decl.name.asString() == "hashCode" &&
decl.valueParameters.size == 1 && decl.codeQlValueParameters.size == 1 &&
decl.valueParameters[0].type.classOrNull?.let { decl.codeQlValueParameters[0].type.classOrNull?.let {
it == realArrayClass it == realArrayClass
} == true } == true
} }
@@ -5155,7 +5155,7 @@ open class KotlinFileExtractor(
val type = useType(eType) val type = useType(eType)
val isAnonymous = eType.isAnonymous val isAnonymous = eType.isAnonymous
val locId = tw.getLocation(e) val locId = tw.getLocation(e)
val valueArgs = (0 until e.valueArgumentsCount).map { e.getValueArgument(it) } val valueArgs = (0 until e.codeQlValueArgumentsCount).map { e.codeQlGetValueArgument(it) }
val id = val id =
if ( if (
@@ -5211,10 +5211,10 @@ open class KotlinFileExtractor(
realCallTarget is IrConstructor && realCallTarget is IrConstructor &&
realCallTarget.parentClassOrNull?.fqNameWhenAvailable?.asString() == realCallTarget.parentClassOrNull?.fqNameWhenAvailable?.asString() ==
"kotlin.Enum" && "kotlin.Enum" &&
realCallTarget.valueParameters.size == 2 && realCallTarget.codeQlValueParameters.size == 2 &&
realCallTarget.valueParameters[0].type == realCallTarget.codeQlValueParameters[0].type ==
pluginContext.irBuiltIns.stringType && pluginContext.irBuiltIns.stringType &&
realCallTarget.valueParameters[1].type == pluginContext.irBuiltIns.intType realCallTarget.codeQlValueParameters[1].type == pluginContext.irBuiltIns.intType
) { ) {
val id0 = val id0 =
@@ -5287,7 +5287,7 @@ open class KotlinFileExtractor(
} }
val args = val args =
(0 until e.typeArgumentsCount).map { e.getTypeArgument(it) }.requireNoNullsOrNull() (0 until e.codeQlTypeArgumentsCount).map { e.codeQlGetTypeArgument(it) }.requireNoNullsOrNull()
if (args == null) { if (args == null) {
logger.warnElement("Found null type argument in enum constructor call", e) logger.warnElement("Found null type argument in enum constructor call", e)
return return
@@ -5365,7 +5365,7 @@ open class KotlinFileExtractor(
// Check for an expression like x = get(x).op(e): // Check for an expression like x = get(x).op(e):
val opReceiver = updateRhs.dispatchReceiver val opReceiver = updateRhs.dispatchReceiver
if (isExpectedLhs(opReceiver)) { if (isExpectedLhs(opReceiver)) {
updateRhs.getValueArgument(0) updateRhs.codeQlGetValueArgument(0)
} else null } else null
} else null } else null
} }
@@ -5560,7 +5560,7 @@ open class KotlinFileExtractor(
"set" "set"
) )
) { ) {
val updateRhs0 = arraySetCall.getValueArgument(1) val updateRhs0 = arraySetCall.codeQlGetValueArgument(1)
if (updateRhs0 == null) { if (updateRhs0 == null) {
logger.errorElement("Update RHS not found", e) logger.errorElement("Update RHS not found", e)
return false return false
@@ -6403,12 +6403,12 @@ open class KotlinFileExtractor(
val ids = getLocallyVisibleFunctionLabels(e.function) val ids = getLocallyVisibleFunctionLabels(e.function)
val locId = tw.getLocation(e) val locId = tw.getLocation(e)
val ext = e.function.extensionReceiverParameter val ext = e.function.codeQlExtensionReceiverParameter
val parameters = val parameters =
if (ext != null) { if (ext != null) {
listOf(ext) + e.function.valueParameters listOf(ext) + e.function.codeQlValueParameters
} else { } else {
e.function.valueParameters e.function.codeQlValueParameters
} }
var types = parameters.map { it.type } var types = parameters.map { it.type }
@@ -6670,7 +6670,7 @@ open class KotlinFileExtractor(
is IrFunction -> { is IrFunction -> {
if ( if (
ownerParent.dispatchReceiverParameter == owner && ownerParent.dispatchReceiverParameter == owner &&
ownerParent.extensionReceiverParameter != null ownerParent.codeQlExtensionReceiverParameter != null
) { ) {
val ownerParent2 = ownerParent.parent val ownerParent2 = ownerParent.parent
@@ -7089,7 +7089,7 @@ open class KotlinFileExtractor(
makeReceiverInfo(callableReferenceExpr.dispatchReceiver, 0) makeReceiverInfo(callableReferenceExpr.dispatchReceiver, 0)
private val extensionReceiverInfo = private val extensionReceiverInfo =
makeReceiverInfo( makeReceiverInfo(
callableReferenceExpr.extensionReceiver, callableReferenceExpr.codeQlExtensionReceiver,
if (dispatchReceiverInfo == null) 0 else 1 if (dispatchReceiverInfo == null) 0 else 1
) )
@@ -7627,8 +7627,8 @@ open class KotlinFileExtractor(
} }
val expressionTypeArguments = val expressionTypeArguments =
(0 until propertyReferenceExpr.typeArgumentsCount).mapNotNull { (0 until propertyReferenceExpr.codeQlTypeArgumentsCount).mapNotNull {
propertyReferenceExpr.getTypeArgument(it) propertyReferenceExpr.codeQlGetTypeArgument(it)
} }
val idPropertyRef = tw.getFreshIdLabel<DbPropertyref>() val idPropertyRef = tw.getFreshIdLabel<DbPropertyref>()
@@ -7829,7 +7829,7 @@ open class KotlinFileExtractor(
if ( if (
functionReferenceExpr.dispatchReceiver != null && functionReferenceExpr.dispatchReceiver != null &&
functionReferenceExpr.extensionReceiver != null functionReferenceExpr.codeQlExtensionReceiver != null
) { ) {
logger.errorElement( logger.errorElement(
"Unexpected: dispatchReceiver and extensionReceiver are both non-null", "Unexpected: dispatchReceiver and extensionReceiver are both non-null",
@@ -7840,7 +7840,7 @@ open class KotlinFileExtractor(
if ( if (
target.owner.dispatchReceiverParameter != null && target.owner.dispatchReceiverParameter != null &&
target.owner.extensionReceiverParameter != null target.owner.codeQlExtensionReceiverParameter != null
) { ) {
logger.errorElement( logger.errorElement(
"Unexpected: dispatch and extension parameters are both non-null", "Unexpected: dispatch and extension parameters are both non-null",
@@ -7899,8 +7899,8 @@ open class KotlinFileExtractor(
null null
} }
expressionTypeArguments = expressionTypeArguments =
(0 until functionReferenceExpr.typeArgumentsCount).mapNotNull { (0 until functionReferenceExpr.codeQlTypeArgumentsCount).mapNotNull {
functionReferenceExpr.getTypeArgument(it) functionReferenceExpr.codeQlGetTypeArgument(it)
} }
dispatchReceiverIdx = -1 dispatchReceiverIdx = -1
} }
@@ -7965,7 +7965,7 @@ open class KotlinFileExtractor(
functionReferenceExpr, functionReferenceExpr,
declarationParent, declarationParent,
null, null,
{ it.valueParameters.size == 1 } { it.codeQlValueParameters.size == 1 }
) { ) {
// The argument to FunctionReference's constructor is the function arity. // The argument to FunctionReference's constructor is the function arity.
extractConstantInteger( extractConstantInteger(
@@ -8572,7 +8572,7 @@ open class KotlinFileExtractor(
reverse: Boolean = false reverse: Boolean = false
) { ) {
val typeArguments = val typeArguments =
(0 until c.typeArgumentsCount).map { c.getTypeArgument(it) }.requireNoNullsOrNull() (0 until c.codeQlTypeArgumentsCount).map { c.codeQlGetTypeArgument(it) }.requireNoNullsOrNull()
if (typeArguments == null) { if (typeArguments == null) {
logger.errorElement("Found a null type argument for a member access expression", c) logger.errorElement("Found a null type argument for a member access expression", c)
} else { } else {
@@ -8923,11 +8923,11 @@ open class KotlinFileExtractor(
tw.writeVariableBinding(lhsId, fieldId) tw.writeVariableBinding(lhsId, fieldId)
val parameters = mutableListOf<IrValueParameter>() val parameters = mutableListOf<IrValueParameter>()
val extParam = samMember.extensionReceiverParameter val extParam = samMember.codeQlExtensionReceiverParameter
if (extParam != null) { if (extParam != null) {
parameters.add(extParam) parameters.add(extParam)
} }
parameters.addAll(samMember.valueParameters) parameters.addAll(samMember.codeQlValueParameters)
fun extractArgument( fun extractArgument(
p: IrValueParameter, p: IrValueParameter,
@@ -9032,7 +9032,7 @@ open class KotlinFileExtractor(
elementToReportOn: IrElement, elementToReportOn: IrElement,
declarationParent: IrDeclarationParent, declarationParent: IrDeclarationParent,
compilerGeneratedKindOverride: CompilerGeneratedKinds? = null, compilerGeneratedKindOverride: CompilerGeneratedKinds? = null,
superConstructorSelector: (IrFunction) -> Boolean = { it.valueParameters.isEmpty() }, superConstructorSelector: (IrFunction) -> Boolean = { it.codeQlValueParameters.isEmpty() },
extractSuperconstructorArgs: (Label<DbSuperconstructorinvocationstmt>) -> Unit = {}, extractSuperconstructorArgs: (Label<DbSuperconstructorinvocationstmt>) -> Unit = {},
): Label<out DbClassorinterface> { ): Label<out DbClassorinterface> {
// Write class // Write class

View File

@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.addAnnotations import com.github.codeql.utils.versions.codeQlAddAnnotations
import org.jetbrains.kotlin.ir.types.classFqName import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
@@ -355,7 +355,7 @@ open class KotlinUsesExtractor(
} }
private fun propertySignature(p: IrProperty) = private fun propertySignature(p: IrProperty) =
((p.getter ?: p.setter)?.extensionReceiverParameter?.let { ((p.getter ?: p.setter)?.codeQlExtensionReceiverParameter?.let {
useType(erase(it.type)).javaResult.signature useType(erase(it.type)).javaResult.signature
} ?: "") } ?: "")
@@ -368,7 +368,7 @@ open class KotlinUsesExtractor(
// useDeclarationParent -> useFunction // useDeclarationParent -> useFunction
// -> extractFunctionLaterIfExternalFileMember, which would result for `fun <T> f(t: // -> extractFunctionLaterIfExternalFileMember, which would result for `fun <T> f(t:
// T) { ... }` for example. // T) { ... }` for example.
(listOfNotNull(d.extensionReceiverParameter) + d.valueParameters) (listOfNotNull(d.codeQlExtensionReceiverParameter) + d.codeQlValueParameters)
.map { useType(erase(it.type)).javaResult.signature } .map { useType(erase(it.type)).javaResult.signature }
.joinToString(separator = ",", prefix = "(", postfix = ")") .joinToString(separator = ",", prefix = "(", postfix = ")")
is IrProperty -> propertySignature(d) + externalClassExtractor.propertySignature is IrProperty -> propertySignature(d) + externalClassExtractor.propertySignature
@@ -488,8 +488,8 @@ open class KotlinUsesExtractor(
val result = val result =
replacementClass.declarations.findSubType<IrSimpleFunction> { replacementDecl -> replacementClass.declarations.findSubType<IrSimpleFunction> { replacementDecl ->
replacementDecl.name == f.name && replacementDecl.name == f.name &&
replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.codeQlValueParameters.size == f.codeQlValueParameters.size &&
replacementDecl.valueParameters.zip(f.valueParameters).all { replacementDecl.codeQlValueParameters.zip(f.codeQlValueParameters).all {
erase(it.first.type) == erase(it.second.type) erase(it.first.type) == erase(it.second.type)
} }
} }
@@ -1265,7 +1265,7 @@ open class KotlinUsesExtractor(
private fun getWildcardSuppressionDirective(t: IrAnnotationContainer): Boolean? = private fun getWildcardSuppressionDirective(t: IrAnnotationContainer): Boolean? =
t.getAnnotation(jvmWildcardSuppressionAnnotation)?.let { t.getAnnotation(jvmWildcardSuppressionAnnotation)?.let {
@Suppress("USELESS_CAST") // `as? Boolean` is not needed for Kotlin < 2.1 @Suppress("USELESS_CAST") // `as? Boolean` is not needed for Kotlin < 2.1
(it.getValueArgument(0) as? CodeQLIrConst<Boolean>)?.value as? Boolean ?: true (it.codeQlGetValueArgument(0) as? CodeQLIrConst<Boolean>)?.value as? Boolean ?: true
} }
private fun addJavaLoweringArgumentWildcards( private fun addJavaLoweringArgumentWildcards(
@@ -1376,9 +1376,9 @@ open class KotlinUsesExtractor(
f.parent, f.parent,
parentId, parentId,
getFunctionShortName(f).nameInDB, getFunctionShortName(f).nameInDB,
(maybeParameterList ?: f.valueParameters).map { it.type }, (maybeParameterList ?: f.codeQlValueParameters).map { it.type },
getAdjustedReturnType(f), getAdjustedReturnType(f),
f.extensionReceiverParameter?.type, f.codeQlExtensionReceiverParameter?.type,
getFunctionTypeParameters(f), getFunctionTypeParameters(f),
classTypeArgsIncludingOuterClasses, classTypeArgsIncludingOuterClasses,
overridesCollectionsMethodWithAlteredParameterTypes(f), overridesCollectionsMethodWithAlteredParameterTypes(f),
@@ -1401,12 +1401,12 @@ open class KotlinUsesExtractor(
// The name of the function; normally f.name.asString(). // The name of the function; normally f.name.asString().
name: String, name: String,
// The types of the value parameters that the functions takes; normally // The types of the value parameters that the functions takes; normally
// f.valueParameters.map { it.type }. // f.codeQlValueParameters.map { it.type }.
parameterTypes: List<IrType>, parameterTypes: List<IrType>,
// The return type of the function; normally f.returnType. // The return type of the function; normally f.returnType.
returnType: IrType, returnType: IrType,
// The extension receiver of the function, if any; normally // The extension receiver of the function, if any; normally
// f.extensionReceiverParameter?.type. // f.codeQlExtensionReceiverParameter?.type.
extensionParamType: IrType?, extensionParamType: IrType?,
// The type parameters of the function. This does not include type parameters of enclosing // The type parameters of the function. This does not include type parameters of enclosing
// classes. // classes.
@@ -1579,7 +1579,7 @@ open class KotlinUsesExtractor(
parentClass.fqNameWhenAvailable?.asString() != parentClass.fqNameWhenAvailable?.asString() !=
"java.util.concurrent.ConcurrentHashMap" || "java.util.concurrent.ConcurrentHashMap" ||
getFunctionShortName(f).nameInDB != "keySet" || getFunctionShortName(f).nameInDB != "keySet" ||
f.valueParameters.isNotEmpty() || f.codeQlValueParameters.isNotEmpty() ||
f.returnType.classFqName?.asString() != "kotlin.collections.MutableSet" f.returnType.classFqName?.asString() != "kotlin.collections.MutableSet"
) { ) {
return f.returnType return f.returnType
@@ -1587,7 +1587,7 @@ open class KotlinUsesExtractor(
val otherKeySet = val otherKeySet =
parentClass.declarations.findSubType<IrFunction> { parentClass.declarations.findSubType<IrFunction> {
it.name.asString() == "keySet" && it.valueParameters.size == 1 it.name.asString() == "keySet" && it.codeQlValueParameters.size == 1
} ?: return f.returnType } ?: return f.returnType
return otherKeySet.returnType.codeQlWithHasQuestionMark(false) return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
@@ -1695,8 +1695,8 @@ open class KotlinUsesExtractor(
javaClass.declarations.findSubType<IrFunction> { decl -> javaClass.declarations.findSubType<IrFunction> { decl ->
!decl.isFakeOverride && !decl.isFakeOverride &&
decl.name.asString() == jvmName && decl.name.asString() == jvmName &&
decl.valueParameters.size == f.valueParameters.size && decl.codeQlValueParameters.size == f.codeQlValueParameters.size &&
decl.valueParameters.zip(f.valueParameters).all { p -> decl.codeQlValueParameters.zip(f.codeQlValueParameters).all { p ->
erase(p.first.type).classifierOrNull == erase(p.first.type).classifierOrNull ==
erase(p.second.type).classifierOrNull erase(p.second.type).classifierOrNull
} }
@@ -2125,7 +2125,7 @@ open class KotlinUsesExtractor(
} }
return if (t.arguments.isNotEmpty()) return if (t.arguments.isNotEmpty())
t.addAnnotations(listOf(RawTypeAnnotation.annotationConstructor)) t.codeQlAddAnnotations(listOf(RawTypeAnnotation.annotationConstructor))
else t else t
} }
} }
@@ -2153,7 +2153,7 @@ open class KotlinUsesExtractor(
val idxOffset = val idxOffset =
if ( if (
declarationParent is IrFunction && declarationParent is IrFunction &&
declarationParent.extensionReceiverParameter != null declarationParent.codeQlExtensionReceiverParameter != null
) )
// For extension functions increase the index to match what the java extractor sees: // For extension functions increase the index to match what the java extractor sees:
1 1
@@ -2187,7 +2187,7 @@ open class KotlinUsesExtractor(
// Gets a field's corresponding property's extension receiver type, if any // Gets a field's corresponding property's extension receiver type, if any
fun getExtensionReceiverType(f: IrField) = fun getExtensionReceiverType(f: IrField) =
f.correspondingPropertySymbol?.owner?.let { f.correspondingPropertySymbol?.owner?.let {
(it.getter ?: it.setter)?.extensionReceiverParameter?.type (it.getter ?: it.setter)?.codeQlExtensionReceiverParameter?.type
} }
fun getFieldLabel(f: IrField): String { fun getFieldLabel(f: IrField): String {
@@ -2222,14 +2222,14 @@ open class KotlinUsesExtractor(
val setter = p.setter val setter = p.setter
val func = getter ?: setter val func = getter ?: setter
val ext = func?.extensionReceiverParameter val ext = func?.codeQlExtensionReceiverParameter
return if (ext == null) { return if (ext == null) {
"@\"property;{$parentId};${p.name.asString()}\"" "@\"property;{$parentId};${p.name.asString()}\""
} else { } else {
val returnType = val returnType =
getter?.returnType getter?.returnType
?: setter?.valueParameters?.singleOrNull()?.type ?: setter?.codeQlValueParameters?.singleOrNull()?.type
?: pluginContext.irBuiltIns.unitType ?: pluginContext.irBuiltIns.unitType
val typeParams = getFunctionTypeParameters(func) val typeParams = getFunctionTypeParameters(func)

View File

@@ -1,5 +1,10 @@
package com.github.codeql package com.github.codeql
import com.github.codeql.utils.versions.codeQlAnnotationFromSymbolOwner
import com.github.codeql.utils.versions.codeQlGetValueArgument
import com.github.codeql.utils.versions.codeQlPutValueArgument
import com.github.codeql.utils.versions.codeQlSetAnnotations
import com.github.codeql.utils.versions.codeQlSetDispatchReceiverParameter
import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor
import java.lang.annotation.ElementType import java.lang.annotation.ElementType
import java.util.HashSet import java.util.HashSet
@@ -95,7 +100,7 @@ class MetaAnnotationSupport(
JvmAnnotationNames.REPEATABLE_ANNOTATION JvmAnnotationNames.REPEATABLE_ANNOTATION
} }
return if (jvmRepeatable != null) { return if (jvmRepeatable != null) {
((jvmRepeatable.getValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol) ((jvmRepeatable.codeQlGetValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol)
?.owner ?.owner
} else { } else {
getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass) getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass)
@@ -117,12 +122,12 @@ class MetaAnnotationSupport(
) )
return null return null
} else { } else {
return IrConstructorCallImpl.fromSymbolOwner( return codeQlAnnotationFromSymbolOwner(
containerClass.defaultType, containerClass.defaultType,
containerConstructor.symbol containerConstructor.symbol
) )
.apply { .apply {
putValueArgument( codeQlPutValueArgument(
0, 0,
IrVarargImpl( IrVarargImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
@@ -144,7 +149,7 @@ class MetaAnnotationSupport(
// Taken from AdditionalClassAnnotationLowering.kt // Taken from AdditionalClassAnnotationLowering.kt
private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTarget>? { private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTarget>? {
val valueArgument = targetEntry.getValueArgument(0) as? IrVararg ?: return null val valueArgument = targetEntry.codeQlGetValueArgument(0) as? IrVararg ?: return null
return valueArgument.elements return valueArgument.elements
.filterIsInstance<IrGetEnumValue>() .filterIsInstance<IrGetEnumValue>()
.mapNotNull { KotlinTarget.valueOrNull(it.symbol.owner.name.asString()) } .mapNotNull { KotlinTarget.valueOrNull(it.symbol.owner.name.asString()) }
@@ -230,14 +235,14 @@ class MetaAnnotationSupport(
) )
} }
return IrConstructorCallImpl.fromSymbolOwner( return codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
targetConstructor.returnType, targetConstructor.returnType,
targetConstructor.symbol, targetConstructor.symbol,
0 0
) )
.apply { putValueArgument(0, vararg) } .apply { codeQlPutValueArgument(0, vararg) }
} }
private val javaAnnotationRetention by lazy { private val javaAnnotationRetention by lazy {
@@ -263,7 +268,7 @@ class MetaAnnotationSupport(
// Taken from AnnotationCodegen.kt (not available in Kotlin < 1.6.20) // Taken from AnnotationCodegen.kt (not available in Kotlin < 1.6.20)
private fun IrClass.getAnnotationRetention(): KotlinRetention? { private fun IrClass.getAnnotationRetention(): KotlinRetention? {
val retentionArgument = val retentionArgument =
getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(0) as? IrGetEnumValue getAnnotation(StandardNames.FqNames.retention)?.codeQlGetValueArgument(0) as? IrGetEnumValue
?: return null ?: return null
val retentionArgumentValue = retentionArgument.symbol.owner val retentionArgumentValue = retentionArgument.symbol.owner
return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) return KotlinRetention.valueOf(retentionArgumentValue.name.asString())
@@ -283,7 +288,7 @@ class MetaAnnotationSupport(
val targetConstructor = val targetConstructor =
retentionType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null retentionType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
return IrConstructorCallImpl.fromSymbolOwner( return codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
targetConstructor.returnType, targetConstructor.returnType,
@@ -291,7 +296,7 @@ class MetaAnnotationSupport(
0 0
) )
.apply { .apply {
putValueArgument( codeQlPutValueArgument(
0, 0,
IrGetEnumValueImpl( IrGetEnumValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
@@ -333,7 +338,7 @@ class MetaAnnotationSupport(
return return
} }
val newParam = thisReceiever.copyTo(this) val newParam = thisReceiever.copyTo(this)
dispatchReceiverParameter = newParam codeQlSetDispatchReceiverParameter(newParam)
body = body =
factory factory
.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) .createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
@@ -406,7 +411,7 @@ class MetaAnnotationSupport(
val repeatableContainerAnnotation = val repeatableContainerAnnotation =
kotlinAnnotationRepeatableContainer?.constructors?.single() kotlinAnnotationRepeatableContainer?.constructors?.single()
containerClass.annotations = codeQlSetAnnotations(containerClass,
annotationClass.annotations annotationClass.annotations
.filter { .filter {
it.isAnnotationWithEqualFqName(StandardNames.FqNames.retention) || it.isAnnotationWithEqualFqName(StandardNames.FqNames.retention) ||
@@ -415,7 +420,7 @@ class MetaAnnotationSupport(
.map { it.deepCopyWithSymbols(containerClass) } + .map { it.deepCopyWithSymbols(containerClass) } +
listOfNotNull( listOfNotNull(
repeatableContainerAnnotation?.let { repeatableContainerAnnotation?.let {
IrConstructorCallImpl.fromSymbolOwner( codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
it.returnType, it.returnType,
@@ -424,6 +429,7 @@ class MetaAnnotationSupport(
) )
} }
) )
)
containerClass containerClass
} }
@@ -462,14 +468,14 @@ class MetaAnnotationSupport(
containerClass.symbol, containerClass.symbol,
containerClass.defaultType containerClass.defaultType
) )
return IrConstructorCallImpl.fromSymbolOwner( return codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
repeatableConstructor.returnType, repeatableConstructor.returnType,
repeatableConstructor.symbol, repeatableConstructor.symbol,
0 0
) )
.apply { putValueArgument(0, containerReference) } .apply { codeQlPutValueArgument(0, containerReference) }
} }
private val javaAnnotationDocumented by lazy { private val javaAnnotationDocumented by lazy {
@@ -488,7 +494,7 @@ class MetaAnnotationSupport(
javaAnnotationDocumented?.declarations?.firstIsInstanceOrNull<IrConstructor>() javaAnnotationDocumented?.declarations?.firstIsInstanceOrNull<IrConstructor>()
?: return null ?: return null
return IrConstructorCallImpl.fromSymbolOwner( return codeQlAnnotationFromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
documentedConstructor.returnType, documentedConstructor.returnType,

View File

@@ -1,6 +1,7 @@
package com.github.codeql package com.github.codeql
import com.github.codeql.KotlinUsesExtractor.LocallyVisibleFunctionLabels import com.github.codeql.KotlinUsesExtractor.LocallyVisibleFunctionLabels
import com.github.codeql.utils.versions.codeQlExtensionReceiver
import com.semmle.extractor.java.PopulateFile import com.semmle.extractor.java.PopulateFile
import com.semmle.util.unicode.UTF8Util import com.semmle.util.unicode.UTF8Util
import java.io.BufferedWriter import java.io.BufferedWriter
@@ -331,7 +332,7 @@ open class FileTrapWriter(
is IrCall -> { is IrCall -> {
// Calls have incorrect startOffset, so we adjust them: // Calls have incorrect startOffset, so we adjust them:
val dr = e.dispatchReceiver?.let { getStartOffset(it) } val dr = e.dispatchReceiver?.let { getStartOffset(it) }
val er = e.extensionReceiver?.let { getStartOffset(it) } val er = e.codeQlExtensionReceiver?.let { getStartOffset(it) }
offsetMinOf(e.startOffset, dr, er) offsetMinOf(e.startOffset, dr, er)
} }
else -> e.startOffset else -> e.startOffset

View File

@@ -2,6 +2,7 @@ package com.github.codeql.comments
import com.github.codeql.* import com.github.codeql.*
import com.github.codeql.utils.isLocalFunction import com.github.codeql.utils.isLocalFunction
import com.github.codeql.utils.versions.codeQlExtensionReceiverParameter
import com.github.codeql.utils.versions.isDispatchReceiver import com.github.codeql.utils.versions.isDispatchReceiver
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -11,7 +12,7 @@ import org.jetbrains.kotlin.ir.util.parentClassOrNull
private fun IrValueParameter.isExtensionReceiver(): Boolean { private fun IrValueParameter.isExtensionReceiver(): Boolean {
val parentFun = parent as? IrFunction ?: return false val parentFun = parent as? IrFunction ?: return false
return parentFun.extensionReceiverParameter == this return parentFun.codeQlExtensionReceiverParameter == this
} }
open class CommentExtractor( open class CommentExtractor(

View File

@@ -1,6 +1,8 @@
package com.github.codeql.utils package com.github.codeql.utils
import com.github.codeql.utils.versions.CodeQLIrConst import com.github.codeql.utils.versions.CodeQLIrConst
import com.github.codeql.utils.versions.codeQlGetValueArgument
import com.github.codeql.utils.versions.codeQlValueArgumentsCount
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -76,9 +78,9 @@ private fun getSpecialJvmName(f: IrFunction): String? {
fun getJvmName(container: IrAnnotationContainer): String? { fun getJvmName(container: IrAnnotationContainer): String? {
for (a: IrConstructorCall in container.annotations) { for (a: IrConstructorCall in container.annotations) {
val t = a.type val t = a.type
if (t is IrSimpleType && a.valueArgumentsCount == 1) { if (t is IrSimpleType && a.codeQlValueArgumentsCount == 1) {
val owner = t.classifier.owner val owner = t.classifier.owner
val v = a.getValueArgument(0) val v = a.codeQlGetValueArgument(0)
if (owner is IrClass) { if (owner is IrClass) {
val aPkg = owner.packageFqName?.asString() val aPkg = owner.packageFqName?.asString()
val name = owner.name.asString() val name = owner.name.asString()

View File

@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.types.addAnnotations import com.github.codeql.utils.versions.codeQlAddAnnotations
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.types.makeNullable
@@ -192,7 +192,7 @@ object RawTypeAnnotation {
addConstructor { isPrimary = true } addConstructor { isPrimary = true }
} }
val constructor = annoClass.constructors.single() val constructor = annoClass.constructors.single()
IrConstructorCallImpl.fromSymbolOwner(constructor.constructedClassType, constructor.symbol) codeQlAnnotationFromSymbolOwner(constructor.constructedClassType, constructor.symbol)
} }
} }
@@ -202,7 +202,7 @@ fun IrType.toRawType(): IrType =
when (val owner = this.classifier.owner) { when (val owner = this.classifier.owner) {
is IrClass -> { is IrClass -> {
if (this.arguments.isNotEmpty()) if (this.arguments.isNotEmpty())
this.addAnnotations(listOf(RawTypeAnnotation.annotationConstructor)) this.codeQlAddAnnotations(listOf(RawTypeAnnotation.annotationConstructor))
else this else this
} }
is IrTypeParameter -> owner.superTypes[0].toRawType() is IrTypeParameter -> owner.superTypes[0].toRawType()
@@ -215,7 +215,7 @@ fun IrType.toRawType(): IrType =
fun IrClass.toRawType(): IrType { fun IrClass.toRawType(): IrType {
val result = this.typeWith(listOf()) val result = this.typeWith(listOf())
return if (this.typeParameters.isNotEmpty()) return if (this.typeParameters.isNotEmpty())
result.addAnnotations(listOf(RawTypeAnnotation.annotationConstructor)) result.codeQlAddAnnotations(listOf(RawTypeAnnotation.annotationConstructor))
else result else result
} }

View File

@@ -0,0 +1,70 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.addAnnotations
/**
* Compatibility accessors for pre-2.4.0 API patterns.
* In pre-2.4.0 versions, these delegate directly to the existing APIs.
*/
// IrFunction: valueParameters
val IrFunction.codeQlValueParameters: List<IrValueParameter>
get() = valueParameters
// IrFunction: extensionReceiverParameter
val IrFunction.codeQlExtensionReceiverParameter: IrValueParameter?
get() = extensionReceiverParameter
// IrMemberAccessExpression: valueArgumentsCount
val IrMemberAccessExpression<*>.codeQlValueArgumentsCount: Int
get() = valueArgumentsCount
// IrMemberAccessExpression: getValueArgument
fun IrMemberAccessExpression<*>.codeQlGetValueArgument(index: Int): IrExpression? = getValueArgument(index)
// IrMemberAccessExpression: putValueArgument
fun IrMemberAccessExpression<*>.codeQlPutValueArgument(index: Int, value: IrExpression?) {
putValueArgument(index, value)
}
// IrMemberAccessExpression: extensionReceiver
val IrMemberAccessExpression<*>.codeQlExtensionReceiver: IrExpression?
get() = extensionReceiver
// IrMemberAccessExpression: typeArgumentsCount
val IrMemberAccessExpression<*>.codeQlTypeArgumentsCount: Int
get() = typeArgumentsCount
// IrMemberAccessExpression: getTypeArgument
fun IrMemberAccessExpression<*>.codeQlGetTypeArgument(index: Int): IrType? = getTypeArgument(index)
// addAnnotations compat: in pre-2.4.0, addAnnotations expects List<IrConstructorCall>
fun IrType.codeQlAddAnnotations(annotations: List<IrConstructorCall>): IrType =
addAnnotations(annotations)
// IrMutableAnnotationContainer.annotations setter: in pre-2.4.0, annotations is var with List<IrConstructorCall>
fun codeQlSetAnnotations(container: org.jetbrains.kotlin.ir.declarations.IrMutableAnnotationContainer, annotations: List<IrConstructorCall>) {
container.annotations = annotations
}
// IrFunction: set dispatch receiver parameter (pre-2.4.0 it's a var)
fun IrFunction.codeQlSetDispatchReceiverParameter(param: IrValueParameter?) {
dispatchReceiverParameter = param
}
// In pre-2.4.0, annotations are List<IrConstructorCall> so IrConstructorCallImpl works directly.
fun codeQlAnnotationFromSymbolOwner(
startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int
): IrConstructorCall =
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, symbol, typeArgumentsCount)
fun codeQlAnnotationFromSymbolOwner(type: IrType, symbol: IrConstructorSymbol): IrConstructorCall =
IrConstructorCallImpl.fromSymbolOwner(type, symbol)

View File

@@ -3,10 +3,32 @@
package com.github.codeql package com.github.codeql
import com.intellij.mock.MockProject
import com.intellij.openapi.extensions.LoadingOrder
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
@OptIn(ExperimentalCompilerApi::class) @OptIn(ExperimentalCompilerApi::class)
abstract class Kotlin2ComponentRegistrar : ComponentRegistrar { abstract class Kotlin2ComponentRegistrar : ComponentRegistrar {
/* Nothing to do; supportsK2 doesn't exist yet. */ /* Nothing to do; supportsK2 doesn't exist yet. */
private var project: MockProject? = null
override fun registerProjectComponents(
project: MockProject,
configuration: CompilerConfiguration
) {
this.project = project
doRegisterExtensions(configuration)
}
abstract fun doRegisterExtensions(configuration: CompilerConfiguration)
fun registerExtractorExtension(extension: IrGenerationExtension) {
val p = project ?: throw IllegalStateException("registerExtractorExtension called before registerProjectComponents")
val extensionPoint = p.extensionArea.getExtensionPoint(IrGenerationExtension.extensionPointName)
extensionPoint.registerExtension(extension, LoadingOrder.LAST, p)
}
} }

View File

@@ -3,11 +3,35 @@
package com.github.codeql package com.github.codeql
import com.intellij.mock.MockProject
import com.intellij.openapi.extensions.LoadingOrder
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
@OptIn(ExperimentalCompilerApi::class) @OptIn(ExperimentalCompilerApi::class)
abstract class Kotlin2ComponentRegistrar : ComponentRegistrar { abstract class Kotlin2ComponentRegistrar : ComponentRegistrar {
override val supportsK2: Boolean override val supportsK2: Boolean
get() = true get() = true
private var project: MockProject? = null
override fun registerProjectComponents(
project: MockProject,
configuration: CompilerConfiguration
) {
this.project = project
doRegisterExtensions(configuration)
}
abstract fun doRegisterExtensions(configuration: CompilerConfiguration)
fun registerExtractorExtension(extension: IrGenerationExtension) {
val p = project ?: throw IllegalStateException("registerExtractorExtension called before registerProjectComponents")
// Register with LoadingOrder.LAST to ensure the extractor runs after other
// IR generation plugins (like kotlinx.serialization) have generated their code.
val extensionPoint = p.extensionArea.getExtensionPoint(IrGenerationExtension.extensionPointName)
extensionPoint.registerExtension(extension, LoadingOrder.LAST, p)
}
} }

View File

@@ -0,0 +1,121 @@
@file:Suppress("DEPRECATION")
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrAnnotation
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrAnnotationImpl
import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.addAnnotations
/**
* Compatibility accessors for pre-2.4.0 API patterns.
* In 2.4.0, valueParameters/extensionReceiverParameter/extensionReceiver/
* getValueArgument/putValueArgument/valueArgumentsCount/typeArgumentsCount/getTypeArgument
* have been removed. This file provides the 2.4.0 implementations.
*/
// IrFunction: valueParameters -> parameters filtered to Regular kind
val IrFunction.codeQlValueParameters: List<IrValueParameter>
get() = parameters.filter { it.kind == org.jetbrains.kotlin.ir.declarations.IrParameterKind.Regular }
// IrFunction: extensionReceiverParameter
val IrFunction.codeQlExtensionReceiverParameter: IrValueParameter?
get() = parameters.firstOrNull { it.kind == org.jetbrains.kotlin.ir.declarations.IrParameterKind.ExtensionReceiver }
// Helper: get the offset of value arguments in the arguments list
// In 2.4.0, arguments[] includes dispatch/extension receivers before regular params
private fun IrMemberAccessExpression<*>.valueArgumentOffset(): Int {
val owner = symbol.owner as? IrFunction ?: return 0
return owner.parameters.count { it.kind != org.jetbrains.kotlin.ir.declarations.IrParameterKind.Regular }
}
// IrMemberAccessExpression: valueArgumentsCount
val IrMemberAccessExpression<*>.codeQlValueArgumentsCount: Int
get() = arguments.size - valueArgumentOffset()
// IrMemberAccessExpression: getValueArgument
fun IrMemberAccessExpression<*>.codeQlGetValueArgument(index: Int): IrExpression? = arguments[index + valueArgumentOffset()]
// IrMemberAccessExpression: putValueArgument
fun IrMemberAccessExpression<*>.codeQlPutValueArgument(index: Int, value: IrExpression?) {
arguments[index + valueArgumentOffset()] = value
}
// IrMemberAccessExpression: extensionReceiver
// For IrCall/IrFunctionReference, look at symbol.owner (IrFunction) directly.
// For IrPropertyReference, symbol.owner is IrProperty; use the getter's parameters instead.
val IrMemberAccessExpression<*>.codeQlExtensionReceiver: IrExpression?
get() {
val erp = extensionReceiverParameterIndex() ?: return null
return arguments[erp]
}
private fun IrMemberAccessExpression<*>.extensionReceiverParameterIndex(): Int? {
// Direct function owner (IrCall, IrFunctionReference, etc.)
(symbol.owner as? IrFunction)?.codeQlExtensionReceiverParameter?.let {
return it.indexInParameters
}
// Property reference: look at getter or setter function
(this as? org.jetbrains.kotlin.ir.expressions.IrPropertyReference)?.let { propRef ->
propRef.getter?.owner?.codeQlExtensionReceiverParameter?.let {
return it.indexInParameters
}
propRef.setter?.owner?.codeQlExtensionReceiverParameter?.let {
return it.indexInParameters
}
}
return null
}
// IrMemberAccessExpression: typeArgumentsCount
val IrMemberAccessExpression<*>.codeQlTypeArgumentsCount: Int
get() = typeArguments.size
// IrMemberAccessExpression: getTypeArgument
fun IrMemberAccessExpression<*>.codeQlGetTypeArgument(index: Int): IrType? = typeArguments[index]
// addAnnotations compat: in 2.4.0, addAnnotations expects List<IrAnnotation>
// IrConstructorCall implements IrAnnotation in 2.4.0, so filterIsInstance is identity
fun IrType.codeQlAddAnnotations(annotations: List<IrConstructorCall>): IrType =
addAnnotations(annotations.filterIsInstance<IrAnnotation>())
// IrMutableAnnotationContainer.annotations setter: in 2.4.0, expects List<IrAnnotation>
fun codeQlSetAnnotations(container: org.jetbrains.kotlin.ir.declarations.IrMutableAnnotationContainer, annotations: List<IrConstructorCall>) {
container.annotations = annotations.filterIsInstance<IrAnnotation>()
}
// IrFunction: set dispatch receiver parameter
// In 2.4.0, dispatchReceiverParameter is val; modify the parameters list directly.
fun IrFunction.codeQlSetDispatchReceiverParameter(param: IrValueParameter?) {
val existing = parameters.indexOfFirst { it.kind == org.jetbrains.kotlin.ir.declarations.IrParameterKind.DispatchReceiver }
val mutableParams = parameters.toMutableList()
if (existing >= 0) {
if (param != null) {
mutableParams[existing] = param
} else {
mutableParams.removeAt(existing)
}
} else if (param != null) {
param.kind = org.jetbrains.kotlin.ir.declarations.IrParameterKind.DispatchReceiver
mutableParams.add(0, param)
}
parameters = mutableParams
}
// In 2.4.0, annotation lists require IrAnnotation instances.
// Use IrAnnotationImpl.fromSymbolOwner instead of IrConstructorCallImpl.fromSymbolOwner.
fun codeQlAnnotationFromSymbolOwner(
startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int
): IrConstructorCall =
IrAnnotationImpl.fromSymbolOwner(startOffset, endOffset, type, symbol, typeArgumentsCount)
fun codeQlAnnotationFromSymbolOwner(type: IrType, symbol: IrConstructorSymbol): IrConstructorCall =
IrAnnotationImpl.fromSymbolOwner(type, symbol)

View File

@@ -0,0 +1,45 @@
package com.github.codeql
import com.intellij.mock.MockProject
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
@OptIn(ExperimentalCompilerApi::class)
@Suppress("DEPRECATION", "DEPRECATION_ERROR")
abstract class Kotlin2ComponentRegistrar :
CompilerPluginRegistrar(),
org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar {
override val supportsK2: Boolean
get() = true
override val pluginId: String
get() = "kotlin-extractor"
// ComponentRegistrar implementation (legacy path, still called by Kotlin compiler)
override fun registerProjectComponents(
project: MockProject,
configuration: CompilerConfiguration
) {
// Registration is done via ExtensionStorage in Kotlin 2.4+.
// This legacy entry point remains for compatibility with service discovery.
}
private var extensionStorage: CompilerPluginRegistrar.ExtensionStorage? = null
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
this@Kotlin2ComponentRegistrar.extensionStorage = this
doRegisterExtensions(configuration)
}
abstract fun doRegisterExtensions(configuration: CompilerConfiguration)
protected fun registerExtractorExtension(extension: IrGenerationExtension) {
val storage = extensionStorage
?: throw IllegalStateException("registerExtractorExtension called before registerExtensions")
with(storage) {
IrGenerationExtension.registerExtension(extension)
}
}
}

View File

@@ -0,0 +1,13 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrParameterKind
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
fun parameterIndexExcludingReceivers(vp: IrValueParameter): Int {
val offset =
(vp.parent as? IrFunction)?.let { f ->
f.parameters.count { it.kind == IrParameterKind.DispatchReceiver || it.kind == IrParameterKind.ExtensionReceiver || it.kind == IrParameterKind.Context }
} ?: 0
return vp.indexInParameters - offset
}

View File

@@ -0,0 +1 @@
com.github.codeql.KotlinExtractorComponentRegistrar

View File

@@ -11,6 +11,7 @@ VERSIONS = [
"2.2.20-Beta2", "2.2.20-Beta2",
"2.3.0", "2.3.0",
"2.3.20", "2.3.20",
"2.4.0",
] ]
def _version_to_tuple(v): def _version_to_tuple(v):

View File

@@ -1,5 +1,5 @@
{ {
"markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.3.30.", "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.4.10.",
"severity": "error", "severity": "error",
"source": { "source": {
"extractorName": "java", "extractorName": "java",

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved modeling of Apache HttpClient `execute` method sinks for `java/ssrf` and `java/non-https-url`.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Kotlin 2.4.0 can now be analysed.

View File

@@ -11,7 +11,7 @@ extensions:
- ["org.apache.http.client.methods", "HttpPost", False, "HttpPost", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "HttpPost", False, "HttpPost", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "HttpPut", False, "HttpPut", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "HttpPut", False, "HttpPut", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "HttpRequestBase", True, "setURI", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "HttpRequestBase", True, "setURI", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "HttpRequestWrapper", True, "setURI", "(URI)", "", "Argument[0]", "request-forgery", "hq-manual"] - ["org.apache.http.client.methods", "HttpRequestWrapper", True, "setURI", "(URI)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client.methods", "HttpTrace", False, "HttpTrace", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "HttpTrace", False, "HttpTrace", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "RequestBuilder", False, "delete", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "RequestBuilder", False, "delete", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "RequestBuilder", False, "get", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "RequestBuilder", False, "get", "", "", "Argument[0]", "request-forgery", "manual"]
@@ -22,3 +22,29 @@ extensions:
- ["org.apache.http.client.methods", "RequestBuilder", False, "put", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "RequestBuilder", False, "put", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "RequestBuilder", False, "setUri", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "RequestBuilder", False, "setUri", "", "", "Argument[0]", "request-forgery", "manual"]
- ["org.apache.http.client.methods", "RequestBuilder", False, "trace", "", "", "Argument[0]", "request-forgery", "manual"] - ["org.apache.http.client.methods", "RequestBuilder", False, "trace", "", "", "Argument[0]", "request-forgery", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["org.apache.http.client.methods", "RequestBuilder", True, "build", "()", "", "Argument[this]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "delete", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "delete", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "get", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "get", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "getUri", "()", "", "Argument[this]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "head", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "head", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "options", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "options", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "patch", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "patch", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "post", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "post", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "put", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "put", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(URI)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "trace", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
- ["org.apache.http.client.methods", "RequestBuilder", True, "trace", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]

View File

@@ -3,6 +3,11 @@ extensions:
pack: codeql/java-all pack: codeql/java-all
extensible: sinkModel extensible: sinkModel
data: data:
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"] - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"] - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,ResponseHandler)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest)", "", "Argument[0]", "request-forgery", "ai-manual"] - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler)", "", "Argument[0]", "request-forgery", "ai-manual"]
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]

View File

@@ -0,0 +1,45 @@
import java.io.IOException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.protocol.HttpContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ApacheHttpClientExecuteSSRF extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String source = request.getParameter("host"); // $ Source
HttpHost host = new HttpHost(source);
HttpRequest req = new BasicHttpRequest("GET", "/");
HttpUriRequest uriReq = RequestBuilder.get(source).build(); // $ Alert
HttpContext context = null;
HttpClient client = HttpClients.createDefault();
ResponseHandler<Object> handler = null;
client.execute(host, req); // $ Alert
client.execute(host, req, context); // $ Alert
client.execute(host, req, handler); // $ Alert
client.execute(host, req, handler, context); // $ Alert
client.execute(uriReq); // $ Alert
client.execute(uriReq, context); // $ Alert
client.execute(uriReq, handler); // $ Alert
client.execute(uriReq, handler, context); // $ Alert
} catch (Exception e) {
// TODO: handle exception
}
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/javax-validation-constraints:${testdir}/../../../stubs/springframework-5.8.x:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf //semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/javax-validation-constraints:${testdir}/../../../stubs/springframework-5.8.x:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/apache-http-client-4.4.13:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf

View File

@@ -0,0 +1,23 @@
// Generated automatically from org.apache.http.client.HttpClient for testing purposes
package org.apache.http.client;
import java.io.IOException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.protocol.HttpContext;
public interface HttpClient {
HttpResponse execute(HttpHost target, HttpRequest request) throws IOException;
HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException;
<T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException;
<T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
throws IOException;
HttpResponse execute(HttpUriRequest request) throws IOException;
HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException;
<T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException;
<T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
throws IOException;
}

View File

@@ -0,0 +1,9 @@
// Generated automatically from org.apache.http.client.ResponseHandler for testing purposes
package org.apache.http.client;
import org.apache.http.HttpResponse;
public interface ResponseHandler<T> {
T handleResponse(HttpResponse response);
}

View File

@@ -0,0 +1,7 @@
package org.apache.http.impl.client;
import org.apache.http.client.HttpClient;
public abstract class CloseableHttpClient implements HttpClient {
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.apache.http.client.HttpClient for testing purposes
package org.apache.http.impl.client;
import java.io.IOException;
import org.apache.http.impl.client.CloseableHttpClient;
public final class HttpClients {
public static CloseableHttpClient createDefault() { return null; }
}

View File

@@ -21,13 +21,19 @@ file_coverage_languages:
scc_languages: scc_languages:
- TypeScript - TypeScript
- TypeScript Typings - TypeScript Typings
- name: vue
display_name: Vue.js component
scc_languages:
- Vue
github_api_languages: github_api_languages:
- JavaScript - JavaScript
- TypeScript - TypeScript
- Vue
scc_languages: scc_languages:
- JavaScript - JavaScript
- TypeScript - TypeScript
- TypeScript Typings - TypeScript Typings
- Vue
file_types: file_types:
- name: javascript - name: javascript
display_name: JavaScript display_name: JavaScript

View File

@@ -213,11 +213,9 @@ class ExprWithPointsTo extends Expr {
* Gets what this expression might "refer-to" in the given `context`. * Gets what this expression might "refer-to" in the given `context`.
*/ */
predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) { predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) {
exists(ControlFlowNode this_, ControlFlowNode origin_ | this.getAFlowNode()
this_.getNode() = this and origin_.getNode() = origin .(ControlFlowNodeWithPointsTo)
| .refersTo(context, obj, cls, origin.getAFlowNode())
this_.(ControlFlowNodeWithPointsTo).refersTo(context, obj, cls, origin_)
)
} }
/** /**
@@ -228,11 +226,7 @@ class ExprWithPointsTo extends Expr {
*/ */
pragma[nomagic] pragma[nomagic]
predicate refersTo(Object obj, AstNode origin) { predicate refersTo(Object obj, AstNode origin) {
exists(ControlFlowNode this_, ControlFlowNode origin_ | this.getAFlowNode().(ControlFlowNodeWithPointsTo).refersTo(obj, origin.getAFlowNode())
this_.getNode() = this and origin_.getNode() = origin
|
this_.(ControlFlowNodeWithPointsTo).refersTo(obj, origin_)
)
} }
/** /**
@@ -246,22 +240,16 @@ class ExprWithPointsTo extends Expr {
* in the given `context`. * in the given `context`.
*/ */
predicate pointsTo(Context context, Value value, AstNode origin) { predicate pointsTo(Context context, Value value, AstNode origin) {
exists(ControlFlowNode this_, ControlFlowNode origin_ | this.getAFlowNode()
this_.getNode() = this and origin_.getNode() = origin .(ControlFlowNodeWithPointsTo)
| .pointsTo(context, value, origin.getAFlowNode())
this_.(ControlFlowNodeWithPointsTo).pointsTo(context, value, origin_)
)
} }
/** /**
* Holds if this expression might "point-to" to `value` which is from `origin`. * Holds if this expression might "point-to" to `value` which is from `origin`.
*/ */
predicate pointsTo(Value value, AstNode origin) { predicate pointsTo(Value value, AstNode origin) {
exists(ControlFlowNode this_, ControlFlowNode origin_ | this.getAFlowNode().(ControlFlowNodeWithPointsTo).pointsTo(value, origin.getAFlowNode())
this_.getNode() = this and origin_.getNode() = origin
|
this_.(ControlFlowNodeWithPointsTo).pointsTo(value, origin_)
)
} }
/** /**
@@ -487,10 +475,7 @@ class FunctionMetricsWithPointsTo extends FunctionMetrics {
not non_coupling_method(result) and not non_coupling_method(result) and
exists(Call call | call.getScope() = this | exists(Call call | call.getScope() = this |
exists(FunctionObject callee | callee.getFunction() = result | exists(FunctionObject callee | callee.getFunction() = result |
exists(CallNode call_ | call.getAFlowNode().getFunction().(ControlFlowNodeWithPointsTo).refersTo(callee)
call_.getNode() = call and
call_.getFunction().(ControlFlowNodeWithPointsTo).refersTo(callee)
)
) )
or or
exists(Attribute a | call.getFunc() = a | exists(Attribute a | call.getFunc() = a |

View File

@@ -64,7 +64,7 @@ private predicate jump_to_defn(ControlFlowNode use, Definition defn) {
private predicate preferred_jump_to_defn(Expr use, Definition def) { private predicate preferred_jump_to_defn(Expr use, Definition def) {
not use instanceof ClassExpr and not use instanceof ClassExpr and
not use instanceof FunctionExpr and not use instanceof FunctionExpr and
exists(ControlFlowNode useNode | useNode.getNode() = use | jump_to_defn(useNode, def)) jump_to_defn(use.getAFlowNode(), def)
} }
private predicate unique_jump_to_defn(Expr use, Definition def) { private predicate unique_jump_to_defn(Expr use, Definition def) {
@@ -452,7 +452,7 @@ private predicate self_parameter_jump_to_defn_attribute(
* This exists primarily for testing use `getPreferredDefinition()` instead. * This exists primarily for testing use `getPreferredDefinition()` instead.
*/ */
Definition getADefinition(Expr use) { Definition getADefinition(Expr use) {
exists(ControlFlowNode useNode | useNode.getNode() = use | jump_to_defn(useNode, result)) and jump_to_defn(use.getAFlowNode(), result) and
not use instanceof Call and not use instanceof Call and
not use.isArtificial() and not use.isArtificial() and
// Not the use itself // Not the use itself

View File

@@ -1,5 +0,0 @@
---
category: deprecated
---
* The `AstNode.getAFlowNode()` predicate has been deprecated. Use `ControlFlowNode.getNode()` from the other direction instead: replace `e.getAFlowNode() = n` with `n.getNode() = e`. This is a preparatory step towards migrating the dataflow library off the legacy CFG; it has no semantic effect.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Simplified the internal predicates that detect `@staticmethod`, `@classmethod` and `@property` decorators to match the decorator's AST `Name` directly, rather than going through the CFG and requiring the name to resolve globally. Code that shadows these three builtin decorators at the module-scope will now be classified by the decorator name alone; in practice, shadowing these names is extremely rare and the call-graph results are unchanged.

View File

@@ -1,4 +0,0 @@
---
category: deprecated
---
* The `Function.getAReturnValueFlowNode()` predicate has been deprecated. Bind a `Return` node explicitly instead — `exists(Return ret | ret.getScope() = f and n.getNode() = ret.getValue())`. This is a preparatory step towards migrating the dataflow library off the legacy CFG; it has no semantic effect.

View File

@@ -16,26 +16,21 @@ abstract class AstNode extends AstNode_ {
/** Gets the scope that this node occurs in */ /** Gets the scope that this node occurs in */
abstract Scope getScope(); abstract Scope getScope();
/** Gets the location for this AST node */
cached
Location getLocation() { none() }
/** /**
* DEPRECATED: use `ControlFlowNode.getNode()` from the other direction instead;
* that is, replace `e.getAFlowNode() = n` with `n.getNode() = e`. This API is
* being removed to untangle the AST and CFG hierarchies in preparation for
* migrating the dataflow library off the legacy CFG.
*
* Gets a flow node corresponding directly to this node. * Gets a flow node corresponding directly to this node.
* NOTE: For some statements and other purely syntactic elements, * NOTE: For some statements and other purely syntactic elements,
* there may not be a `ControlFlowNode`. * there may not be a `ControlFlowNode`
*/ */
cached cached
deprecated ControlFlowNode getAFlowNode() { ControlFlowNode getAFlowNode() {
Stages::AST::ref() and Stages::AST::ref() and
py_flow_bb_node(result, this, _, _) py_flow_bb_node(result, this, _, _)
} }
/** Gets the location for this AST node */
cached
Location getLocation() { none() }
/** /**
* Whether this syntactic element is artificial, that is it is generated * Whether this syntactic element is artificial, that is it is generated
* by the compiler and is not present in the source * by the compiler and is not present in the source

View File

@@ -28,9 +28,7 @@ class Expr extends Expr_, AstNode {
/** Whether this expression may have a side effect (as determined purely from its syntax) */ /** Whether this expression may have a side effect (as determined purely from its syntax) */
predicate hasSideEffects() { predicate hasSideEffects() {
/* If an exception raised by this expression handled, count that as a side effect */ /* If an exception raised by this expression handled, count that as a side effect */
exists(ControlFlowNode n | n.getNode() = this | this.getAFlowNode().getASuccessor().getNode() instanceof ExceptStmt
n.getASuccessor().getNode() instanceof ExceptStmt
)
or or
this.getASubExpression().hasSideEffects() this.getASubExpression().hasSideEffects()
} }
@@ -70,6 +68,8 @@ class Attribute extends Attribute_ {
/* syntax: Expr.name */ /* syntax: Expr.name */
override Expr getASubExpression() { result = this.getObject() } override Expr getASubExpression() { result = this.getObject() }
override AttrNode getAFlowNode() { result = super.getAFlowNode() }
/** Gets the name of this attribute. That is the `name` in `obj.name` */ /** Gets the name of this attribute. That is the `name` in `obj.name` */
string getName() { result = Attribute_.super.getAttr() } string getName() { result = Attribute_.super.getAttr() }
@@ -96,6 +96,8 @@ class Subscript extends Subscript_ {
} }
Expr getObject() { result = Subscript_.super.getValue() } Expr getObject() { result = Subscript_.super.getValue() }
override SubscriptNode getAFlowNode() { result = super.getAFlowNode() }
} }
/** A call expression, such as `func(...)` */ /** A call expression, such as `func(...)` */
@@ -111,6 +113,8 @@ class Call extends Call_ {
override string toString() { result = this.getFunc().toString() + "()" } override string toString() { result = this.getFunc().toString() + "()" }
override CallNode getAFlowNode() { result = super.getAFlowNode() }
/** Gets a tuple (*) argument of this call. */ /** Gets a tuple (*) argument of this call. */
Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() } Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() }
@@ -196,6 +200,8 @@ class IfExp extends IfExp_ {
override Expr getASubExpression() { override Expr getASubExpression() {
result = this.getTest() or result = this.getBody() or result = this.getOrelse() result = this.getTest() or result = this.getBody() or result = this.getOrelse()
} }
override IfExprNode getAFlowNode() { result = super.getAFlowNode() }
} }
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */ /** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
@@ -404,6 +410,8 @@ class PlaceHolder extends PlaceHolder_ {
override Expr getASubExpression() { none() } override Expr getASubExpression() { none() }
override string toString() { result = "$" + this.getId() } override string toString() { result = "$" + this.getId() }
override NameNode getAFlowNode() { result = super.getAFlowNode() }
} }
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */ /** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
@@ -470,6 +478,8 @@ class Name extends Name_ {
override string toString() { result = this.getId() } override string toString() { result = this.getId() }
override NameNode getAFlowNode() { result = super.getAFlowNode() }
override predicate isArtificial() { override predicate isArtificial() {
/* Artificial variable names in comprehensions all start with "." */ /* Artificial variable names in comprehensions all start with "." */
this.getId().charAt(0) = "." this.getId().charAt(0) = "."
@@ -575,6 +585,8 @@ abstract class NameConstant extends Name, ImmutableLiteral {
override predicate isConstant() { any() } override predicate isConstant() { any() }
override NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() }
override predicate isArtificial() { none() } override predicate isArtificial() { none() }
} }

View File

@@ -555,27 +555,27 @@ class DefinitionNode extends ControlFlowNode {
cached cached
DefinitionNode() { DefinitionNode() {
Stages::AST::ref() and Stages::AST::ref() and
exists(Assign a | this.getNode() = a.getATarget()) exists(Assign a | a.getATarget().getAFlowNode() = this)
or or
exists(AssignExpr a | this.getNode() = a.getTarget()) exists(AssignExpr a | a.getTarget().getAFlowNode() = this)
or or
exists(AnnAssign a | this.getNode() = a.getTarget() and exists(a.getValue())) exists(AnnAssign a | a.getTarget().getAFlowNode() = this and exists(a.getValue()))
or or
exists(Alias a | this.getNode() = a.getAsname()) exists(Alias a | a.getAsname().getAFlowNode() = this)
or or
augstore(_, this) augstore(_, this)
or or
// `x, y = 1, 2` where LHS is a combination of list or tuples // `x, y = 1, 2` where LHS is a combination of list or tuples
exists(Assign a | this.getNode() = list_or_tuple_nested_element(a.getATarget())) exists(Assign a | list_or_tuple_nested_element(a.getATarget()).getAFlowNode() = this)
or or
exists(For for | this.getNode() = for.getTarget()) exists(For for | for.getTarget().getAFlowNode() = this)
or or
exists(Parameter param | this.getNode() = param.asName() and exists(param.getDefault())) exists(Parameter param | this = param.asName().getAFlowNode() and exists(param.getDefault()))
} }
/** flow node corresponding to the value assigned for the definition corresponding to this flow node */ /** flow node corresponding to the value assigned for the definition corresponding to this flow node */
ControlFlowNode getValue() { ControlFlowNode getValue() {
result.getNode() = assigned_value(this.getNode()) and result = assigned_value(this.getNode()).getAFlowNode() and
( (
result.getBasicBlock().dominates(this.getBasicBlock()) result.getBasicBlock().dominates(this.getBasicBlock())
or or
@@ -584,7 +584,7 @@ class DefinitionNode extends ControlFlowNode {
// since the default value for a parameter is evaluated in the same basic block as // since the default value for a parameter is evaluated in the same basic block as
// the function definition, but the parameter belongs to the basic block of the function, // the function definition, but the parameter belongs to the basic block of the function,
// there is no dominance relationship between the two. // there is no dominance relationship between the two.
exists(Parameter param | this.getNode() = param.asName()) exists(Parameter param | this = param.asName().getAFlowNode())
) )
} }
} }
@@ -901,7 +901,7 @@ class ExceptFlowNode extends ControlFlowNode {
exists(ExceptStmt ex | exists(ExceptStmt ex |
this.getBasicBlock().dominates(result.getBasicBlock()) and this.getBasicBlock().dominates(result.getBasicBlock()) and
ex = this.getNode() and ex = this.getNode() and
result.getNode() = ex.getType() result = ex.getType().getAFlowNode()
) )
} }
@@ -913,7 +913,7 @@ class ExceptFlowNode extends ControlFlowNode {
exists(ExceptStmt ex | exists(ExceptStmt ex |
this.getBasicBlock().dominates(result.getBasicBlock()) and this.getBasicBlock().dominates(result.getBasicBlock()) and
ex = this.getNode() and ex = this.getNode() and
result.getNode() = ex.getName() result = ex.getName().getAFlowNode()
) )
} }
} }
@@ -928,7 +928,7 @@ class ExceptGroupFlowNode extends ControlFlowNode {
*/ */
ControlFlowNode getType() { ControlFlowNode getType() {
this.getBasicBlock().dominates(result.getBasicBlock()) and this.getBasicBlock().dominates(result.getBasicBlock()) and
result.getNode() = this.getNode().(ExceptGroupStmt).getType() result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode()
} }
/** /**
@@ -937,7 +937,7 @@ class ExceptGroupFlowNode extends ControlFlowNode {
*/ */
ControlFlowNode getName() { ControlFlowNode getName() {
this.getBasicBlock().dominates(result.getBasicBlock()) and this.getBasicBlock().dominates(result.getBasicBlock()) and
result.getNode() = this.getNode().(ExceptGroupStmt).getName() result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode()
} }
} }

View File

@@ -153,16 +153,8 @@ class Function extends Function_, Scope, AstNode {
override predicate contains(AstNode inner) { Scope.super.contains(inner) } override predicate contains(AstNode inner) { Scope.super.contains(inner) }
/** /** Gets a control flow node for a return value of this function */
* DEPRECATED: bind a `Return` node explicitly instead, e.g. ControlFlowNode getAReturnValueFlowNode() {
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
* This API is being phased out together with `AstNode.getAFlowNode()` to
* untangle the AST and CFG hierarchies in preparation for migrating the
* dataflow library off the legacy CFG.
*
* Gets a control flow node for a return value of this function.
*/
deprecated ControlFlowNode getAReturnValueFlowNode() {
exists(Return ret | exists(Return ret |
ret.getScope() = this and ret.getScope() = this and
ret.getValue() = result.getNode() ret.getValue() = result.getNode()

View File

@@ -162,6 +162,8 @@ class ImportMember extends ImportMember_ {
string getImportedModuleName() { string getImportedModuleName() {
result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName() result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName()
} }
override ImportMemberNode getAFlowNode() { result = super.getAFlowNode() }
} }
/** An import statement */ /** An import statement */

View File

@@ -46,23 +46,20 @@ class SelfAttributeRead extends SelfAttribute {
} }
predicate guardedByHasattr() { predicate guardedByHasattr() {
exists(Variable var, ControlFlowNode n, ControlFlowNode this_, ControlFlowNode obj_ | exists(Variable var, ControlFlowNode n |
this_.getNode() = this and obj_.getNode() = this.getObject() var.getAUse() = this.getObject().getAFlowNode() and
|
var.getAUse() = obj_ and
hasattr(n, var.getAUse(), this.getName()) and hasattr(n, var.getAUse(), this.getName()) and
n.strictlyDominates(this_) n.strictlyDominates(this.getAFlowNode())
) )
} }
pragma[noinline] pragma[noinline]
predicate locallyDefined() { predicate locallyDefined() {
exists(SelfAttributeStore store, ControlFlowNode store_, ControlFlowNode this_ | exists(SelfAttributeStore store |
store_.getNode() = store and this_.getNode() = this
|
this.getName() = store.getName() and this.getName() = store.getName() and
this.getScope() = store.getScope() and this.getScope() = store.getScope()
store_.strictlyDominates(this_) |
store.getAFlowNode().strictlyDominates(this.getAFlowNode())
) )
} }
} }

View File

@@ -5,30 +5,24 @@ private import semmle.python.dataflow.new.DataFlow
private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) { private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
exists(CompareNode cn | cn = g | exists(CompareNode cn | cn = g |
exists(ImmutableLiteral const, Cmpop op, ControlFlowNode c | exists(ImmutableLiteral const, Cmpop op |
c.getNode() = const and op = any(Eq eq) and branch = true
(
op = any(Eq eq) and branch = true
or
op = any(NotEq ne) and branch = false
)
|
cn.operands(c, op, node)
or or
cn.operands(node, op, c) op = any(NotEq ne) and branch = false
|
cn.operands(const.getAFlowNode(), op, node)
or
cn.operands(node, op, const.getAFlowNode())
) )
or or
exists(NameConstant const, Cmpop op, ControlFlowNode c | exists(NameConstant const, Cmpop op |
c.getNode() = const and op = any(Is is_) and branch = true
(
op = any(Is is_) and branch = true
or
op = any(IsNot isn) and branch = false
)
|
cn.operands(c, op, node)
or or
cn.operands(node, op, c) op = any(IsNot isn) and branch = false
|
cn.operands(const.getAFlowNode(), op, node)
or
cn.operands(node, op, const.getAFlowNode())
) )
or or
exists(IterableNode const_iterable, Cmpop op | exists(IterableNode const_iterable, Cmpop op |

View File

@@ -228,7 +228,7 @@ private class ClassDefinitionAsAttrWrite extends AttrWrite, CfgNode {
override Node getValue() { result.asCfgNode() = node.getValue() } override Node getValue() { result.asCfgNode() = node.getValue() }
override Node getObject() { result.asCfgNode().getNode() = cls } override Node getObject() { result.asCfgNode() = cls.getAFlowNode() }
override ExprNode getAttributeNameExpr() { none() } override ExprNode getAttributeNameExpr() { none() }

View File

@@ -256,12 +256,9 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
*/ */
overlay[local] overlay[local]
predicate isStaticmethod(Function func) { predicate isStaticmethod(Function func) {
// The decorator is *syntactically* a `Name` "staticmethod" — we don't exists(NameNode id | id.getId() = "staticmethod" and id.isGlobal() |
// care which variable it resolves to. `staticmethod` is a builtin and func.getADecorator() = id.getNode()
// is almost never shadowed in a module-level scope; even if a class )
// redefines `staticmethod` in its body, the class body has not started
// executing yet at the decorator position, so Python uses the builtin.
func.getADecorator().(Name).getId() = "staticmethod"
} }
/** /**
@@ -271,9 +268,9 @@ predicate isStaticmethod(Function func) {
*/ */
overlay[local] overlay[local]
predicate isClassmethod(Function func) { predicate isClassmethod(Function func) {
// See `isStaticmethod` for the rationale for matching on the AST `Name` exists(NameNode id | id.getId() = "classmethod" and id.isGlobal() |
// rather than going via the CFG and `isGlobal()`. func.getADecorator() = id.getNode()
func.getADecorator().(Name).getId() = "classmethod" )
or or
exists(Class cls | exists(Class cls |
cls.getAMethod() = func and cls.getAMethod() = func and
@@ -288,8 +285,9 @@ predicate isClassmethod(Function func) {
/** Holds if the function `func` has a `property` decorator. */ /** Holds if the function `func` has a `property` decorator. */
overlay[local] overlay[local]
predicate hasPropertyDecorator(Function func) { predicate hasPropertyDecorator(Function func) {
// See `isStaticmethod` for the rationale for matching on the AST `Name`. exists(NameNode id | id.getId() = "property" and id.isGlobal() |
func.getADecorator().(Name).getId() = "property" func.getADecorator() = id.getNode()
)
} }
/** /**
@@ -1913,8 +1911,8 @@ abstract class ReturnNode extends Node {
class ExtractedReturnNode extends ReturnNode, CfgNode { class ExtractedReturnNode extends ReturnNode, CfgNode {
// See `TaintTrackingImplementation::returnFlowStep` // See `TaintTrackingImplementation::returnFlowStep`
ExtractedReturnNode() { ExtractedReturnNode() {
node.getNode() = any(Return ret).getValue() or node = any(Return ret).getValue().getAFlowNode() or
node.getNode() = any(Yield yield) node = any(Yield yield).getAFlowNode()
} }
override ReturnKind getKind() { any() } override ReturnKind getKind() { any() }
@@ -1932,7 +1930,7 @@ class ExtractedReturnNode extends ReturnNode, CfgNode {
class YieldNodeInContextManagerFunction extends ReturnNode, CfgNode { class YieldNodeInContextManagerFunction extends ReturnNode, CfgNode {
YieldNodeInContextManagerFunction() { YieldNodeInContextManagerFunction() {
hasContextmanagerDecorator(node.getScope()) and hasContextmanagerDecorator(node.getScope()) and
node.getNode() = any(Yield yield).getValue() node = any(Yield yield).getValue().getAFlowNode()
} }
override ReturnKind getKind() { any() } override ReturnKind getKind() { any() }

View File

@@ -185,8 +185,8 @@ private predicate synthDictSplatArgumentNodeStoreStep(
*/ */
predicate yieldStoreStep(Node nodeFrom, Content c, Node nodeTo) { predicate yieldStoreStep(Node nodeFrom, Content c, Node nodeTo) {
exists(Yield yield | exists(Yield yield |
nodeTo.asCfgNode().getNode() = yield and nodeTo.asCfgNode() = yield.getAFlowNode() and
nodeFrom.asCfgNode().getNode() = yield.getValue() and nodeFrom.asCfgNode() = yield.getValue().getAFlowNode() and
// TODO: Consider if this will also need to transfer dictionary content // TODO: Consider if this will also need to transfer dictionary content
// once dictionary comprehensions are supported. // once dictionary comprehensions are supported.
c instanceof ListElementContent c instanceof ListElementContent

View File

@@ -485,7 +485,7 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
/** Gets a node that reads this variable, excluding reads that happen through `from ... import *`. */ /** Gets a node that reads this variable, excluding reads that happen through `from ... import *`. */
Node getALocalRead() { Node getALocalRead() {
result.asCfgNode().getNode() = var.getALoad() and result.asCfgNode() = var.getALoad().getAFlowNode() and
not result.getScope() = mod not result.getScope() = mod
} }

View File

@@ -9,19 +9,7 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.ImportStar private import semmle.python.dataflow.new.internal.ImportStar
private import semmle.python.dataflow.new.TypeTracking private import semmle.python.dataflow.new.TypeTracking
private import semmle.python.dataflow.new.internal.DataFlowPrivate private import semmle.python.dataflow.new.internal.DataFlowPrivate
private import semmle.python.essa.SsaDefinitions
/**
* Holds if `init` is a package's `__init__.py` and `var` is a global variable in
* `init` whose name matches a submodule of the package.
*
* Inlined from `SsaSource::init_module_submodule_defn` to avoid pulling
* `semmle.python.essa.SsaDefinitions` into the new dataflow stack.
*/
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
init.isPackageInit() and
exists(init.getPackage().getSubModule(var.getId())) and
var.getScope() = init
}
/** /**
* Python modules and the way imports are resolved are... complicated. Here's a crash course in how * Python modules and the way imports are resolved are... complicated. Here's a crash course in how
@@ -338,7 +326,7 @@ module ImportResolution {
// imported yet. // imported yet.
exists(string submodule, Module package, EssaVariable var | exists(string submodule, Module package, EssaVariable var |
submodule = var.getName() and submodule = var.getName() and
initModuleSubmoduleDefn(var.getSourceVariable(), package) and SsaSource::init_module_submodule_defn(var.getSourceVariable(), package.getEntryNode()) and
m = getModuleFromName(package.getPackageName() + "." + submodule) and m = getModuleFromName(package.getPackageName() + "." + submodule) and
result.asCfgNode() = var.getDefinition().(EssaNodeDefinition).getDefiningNode() result.asCfgNode() = var.getDefinition().(EssaNodeDefinition).getDefiningNode()
) )

View File

@@ -94,10 +94,8 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input {
Node returnOf(Node callable, SummaryComponent return) { Node returnOf(Node callable, SummaryComponent return) {
return = FlowSummaryImpl::Private::SummaryComponent::return() and return = FlowSummaryImpl::Private::SummaryComponent::return() and
// `result` should be the return value of a callable expression (lambda or function) referenced by `callable` // `result` should be the return value of a callable expression (lambda or function) referenced by `callable`
exists(Return ret | result.asCfgNode() =
ret.getScope() = callable.getALocalSource().asExpr().(CallableExpr).getInnerScope() and callable.getALocalSource().asExpr().(CallableExpr).getInnerScope().getAReturnValueFlowNode()
result.asCfgNode().getNode() = ret.getValue()
)
} }
// Relating callables to nodes // Relating callables to nodes

View File

@@ -61,7 +61,7 @@ private module CaptureInput implements Shared::InputSig<Location, Cfg::BasicBloc
class VariableWrite extends ControlFlowNode { class VariableWrite extends ControlFlowNode {
CapturedVariable v; CapturedVariable v;
VariableWrite() { exists(DefinitionNode d | d.getNode() = v.getAStore() | this = d.getValue()) } VariableWrite() { this = v.getAStore().getAFlowNode().(DefinitionNode).getValue() }
CapturedVariable getVariable() { result = v } CapturedVariable getVariable() { result = v }
@@ -71,7 +71,7 @@ private module CaptureInput implements Shared::InputSig<Location, Cfg::BasicBloc
class VariableRead extends Expr { class VariableRead extends Expr {
CapturedVariable v; CapturedVariable v;
VariableRead() { this.getNode() = v.getALoad() } VariableRead() { this = v.getALoad().getAFlowNode() }
CapturedVariable getVariable() { result = v } CapturedVariable getVariable() { result = v }
} }

View File

@@ -448,7 +448,8 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
context = TNoParam() and context = TNoParam() and
src = TTaintTrackingNode_(retval, TNoParam(), path, kind, this) and src = TTaintTrackingNode_(retval, TNoParam(), path, kind, this) and
node.asCfgNode() = call and node.asCfgNode() = call and
retval.asCfgNode().getNode() = any(Return ret | ret.getScope() = pyfunc.getScope()).getValue() retval.asCfgNode() =
any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode()
) and ) and
edgeLabel = "return" edgeLabel = "return"
} }
@@ -470,7 +471,8 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
this.callContexts(call, src, pyfunc, context, callee) and this.callContexts(call, src, pyfunc, context, callee) and
retnode = TTaintTrackingNode_(retval, callee, path, kind, this) and retnode = TTaintTrackingNode_(retval, callee, path, kind, this) and
node.asCfgNode() = call and node.asCfgNode() = call and
retval.asCfgNode().getNode() = any(Return ret | ret.getScope() = pyfunc.getScope()).getValue() retval.asCfgNode() =
any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode()
) and ) and
edgeLabel = "call" edgeLabel = "call"
} }
@@ -714,10 +716,8 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu
src = TTaintTrackingNode_(srcnode, context, path, srckind, this) and src = TTaintTrackingNode_(srcnode, context, path, srckind, this) and
path.noAttribute() path.noAttribute()
| |
srcnode.asCfgNode().getNode() = assign.getValue() and assign.getValue().getAFlowNode() = srcnode.asCfgNode() and
exists(SequenceNode left_parent | left_parent.getNode() = assign.getATarget() | depth = iterable_unpacking_descent(assign.getATarget().getAFlowNode(), defn.getDefiningNode()) and
depth = iterable_unpacking_descent(left_parent, defn.getDefiningNode())
) and
kind = taint_at_depth(srckind, depth) kind = taint_at_depth(srckind, depth)
) )
} }
@@ -964,7 +964,7 @@ private TaintKind taint_at_depth(SequenceKind parent_kind, int depth) {
* - with `left_defn` = `*y`, `left_parent` = `((x, *y), ...)`, result = 1 * - with `left_defn` = `*y`, `left_parent` = `((x, *y), ...)`, result = 1
*/ */
int iterable_unpacking_descent(SequenceNode left_parent, ControlFlowNode left_defn) { int iterable_unpacking_descent(SequenceNode left_parent, ControlFlowNode left_defn) {
exists(Assign a | left_parent.getNode() = a.getATarget().getASubExpression*()) and exists(Assign a | a.getATarget().getASubExpression*().getAFlowNode() = left_parent) and
left_parent.getAnElement() = left_defn and left_parent.getAnElement() = left_defn and
// Handle `a, *b = some_iterable` // Handle `a, *b = some_iterable`
if left_defn instanceof StarredNode then result = 0 else result = 1 if left_defn instanceof StarredNode then result = 0 else result = 1

View File

@@ -56,7 +56,7 @@ module SsaSource {
predicate with_definition(Variable v, ControlFlowNode defn) { predicate with_definition(Variable v, ControlFlowNode defn) {
exists(With with, Name var | exists(With with, Name var |
with.getOptionalVars() = var and with.getOptionalVars() = var and
defn.getNode() = var var.getAFlowNode() = defn
| |
var = v.getAStore() var = v.getAStore()
) )
@@ -67,7 +67,7 @@ module SsaSource {
predicate pattern_capture_definition(Variable v, ControlFlowNode defn) { predicate pattern_capture_definition(Variable v, ControlFlowNode defn) {
exists(MatchCapturePattern capture, Name var | exists(MatchCapturePattern capture, Name var |
capture.getVariable() = var and capture.getVariable() = var and
defn.getNode() = var var.getAFlowNode() = defn
| |
var = v.getAStore() var = v.getAStore()
) )
@@ -78,7 +78,7 @@ module SsaSource {
predicate pattern_alias_definition(Variable v, ControlFlowNode defn) { predicate pattern_alias_definition(Variable v, ControlFlowNode defn) {
exists(MatchAsPattern pattern, Name var | exists(MatchAsPattern pattern, Name var |
pattern.getAlias() = var and pattern.getAlias() = var and
defn.getNode() = var var.getAFlowNode() = defn
| |
var = v.getAStore() var = v.getAStore()
) )

View File

@@ -59,7 +59,7 @@ module Bottle {
override Parameter getARoutedParameter() { none() } override Parameter getARoutedParameter() { none() }
override Function getARequestHandler() { node.getNode() = result.getADecorator() } override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
} }
} }
@@ -73,10 +73,7 @@ module Bottle {
/** A response returned by a view callable. */ /** A response returned by a view callable. */
class BottleReturnResponse extends Http::Server::HttpResponse::Range { class BottleReturnResponse extends Http::Server::HttpResponse::Range {
BottleReturnResponse() { BottleReturnResponse() {
exists(Return ret | this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode()
ret.getScope() = any(View::ViewCallable vc) and
this.asCfgNode().getNode() = ret.getValue()
)
} }
override DataFlow::Node getBody() { result = this } override DataFlow::Node getBody() { result = this }

View File

@@ -2872,10 +2872,7 @@ module PrivateDjango {
DataFlow::CfgNode DataFlow::CfgNode
{ {
DjangoRedirectViewGetRedirectUrlReturn() { DjangoRedirectViewGetRedirectUrlReturn() {
exists(Return ret | node = any(GetRedirectUrlFunction f).getAReturnValueFlowNode()
ret.getScope() = any(GetRedirectUrlFunction f) and
node.getNode() = ret.getValue()
)
} }
override DataFlow::Node getRedirectLocation() { result = this } override DataFlow::Node getRedirectLocation() { result = this }

View File

@@ -129,7 +129,7 @@ module FastApi {
result in [this.getArg(0), this.getArgByName("path")] result in [this.getArg(0), this.getArgByName("path")]
} }
override Function getARequestHandler() { node.getNode() = result.getADecorator() } override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
override string getFramework() { result = "FastAPI" } override string getFramework() { result = "FastAPI" }
@@ -309,10 +309,7 @@ module FastApi {
FastApiRouteSetup routeSetup; FastApiRouteSetup routeSetup;
FastApiRequestHandlerReturn() { FastApiRequestHandlerReturn() {
exists(Return ret | node = routeSetup.getARequestHandler().getAReturnValueFlowNode()
ret.getScope() = routeSetup.getARequestHandler() and
node.getNode() = ret.getValue()
)
} }
override DataFlow::Node getBody() { result = this } override DataFlow::Node getBody() { result = this }

View File

@@ -371,7 +371,7 @@ module Flask {
result in [this.getArg(0), this.getArgByName("rule")] result in [this.getArg(0), this.getArgByName("rule")]
} }
override Function getARequestHandler() { node.getNode() = result.getADecorator() } override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
} }
/** /**
@@ -536,7 +536,7 @@ module Flask {
FlaskRouteHandlerReturn() { FlaskRouteHandlerReturn() {
exists(Function routeHandler | exists(Function routeHandler |
routeHandler = any(FlaskRouteSetup rs).getARequestHandler() and routeHandler = any(FlaskRouteSetup rs).getARequestHandler() and
exists(Return ret | ret.getScope() = routeHandler and node.getNode() = ret.getValue()) and node = routeHandler.getAReturnValueFlowNode() and
not this instanceof Flask::Response::InstanceSource not this instanceof Flask::Response::InstanceSource
) )
} }

View File

@@ -38,7 +38,7 @@ private module FlaskAdmin {
result in [this.getArg(0), this.getArgByName("url")] result in [this.getArg(0), this.getArgByName("url")]
} }
override Function getARequestHandler() { node.getNode() = result.getADecorator() } override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
} }
/** /**
@@ -71,7 +71,7 @@ private module FlaskAdmin {
override Function getARequestHandler() { override Function getARequestHandler() {
exists(Flask::FlaskViewClass cls | exists(Flask::FlaskViewClass cls |
node.getNode() = cls.getADecorator() and cls.getADecorator().getAFlowNode() = node and
result = cls.getARequestHandler() result = cls.getARequestHandler()
) )
} }

View File

@@ -166,10 +166,7 @@ module Pyramid {
/** A response returned by a view callable. */ /** A response returned by a view callable. */
private class PyramidReturnResponse extends Http::Server::HttpResponse::Range { private class PyramidReturnResponse extends Http::Server::HttpResponse::Range {
PyramidReturnResponse() { PyramidReturnResponse() {
exists(Return ret | this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode() and
ret.getScope() = any(View::ViewCallable vc) and
this.asCfgNode().getNode() = ret.getValue()
) and
not this = instance() not this = instance()
} }

View File

@@ -2254,9 +2254,8 @@ module StdlibPrivate {
DataFlow::CfgNode DataFlow::CfgNode
{ {
WsgirefSimpleServerApplicationReturn() { WsgirefSimpleServerApplicationReturn() {
exists(WsgirefSimpleServerApplication requestHandler, Return ret | exists(WsgirefSimpleServerApplication requestHandler |
ret.getScope() = requestHandler and node = requestHandler.getAReturnValueFlowNode()
node.getNode() = ret.getValue()
) )
} }

View File

@@ -182,10 +182,7 @@ private module Twisted {
DataFlow::CfgNode DataFlow::CfgNode
{ {
TwistedResourceRenderMethodReturn() { TwistedResourceRenderMethodReturn() {
exists(Return ret | this.asCfgNode() = any(TwistedResourceRenderMethod meth).getAReturnValueFlowNode()
ret.getScope() = any(TwistedResourceRenderMethod meth) and
this.asCfgNode().getNode() = ret.getValue()
)
} }
override DataFlow::Node getBody() { result = this } override DataFlow::Node getBody() { result = this }

View File

@@ -77,7 +77,7 @@ module Stages {
or or
exists(any(AstExtended::AstNode n).getParentNode()) exists(any(AstExtended::AstNode n).getParentNode())
or or
exists(PyFlow::ControlFlowNode cfg, AstExtended::AstNode n | cfg.getNode() = n) exists(any(AstExtended::AstNode n).getAFlowNode())
or or
exists(any(PyFlow::BasicBlock b).getImmediateDominator()) exists(any(PyFlow::BasicBlock b).getImmediateDominator())
or or

Some files were not shown because too many files have changed in this diff Show More