Compare commits

...

187 Commits

Author SHA1 Message Date
Anders Fugmann
b89b6e432a Kotlin 2.4.0: Use IrAnnotationImpl for annotation creation
In 2.4.0, annotation lists are typed as List<IrAnnotation> and
IrConstructorCallImpl does not extend IrAnnotation. Replace all
IrConstructorCallImpl.fromSymbolOwner() calls that create annotations
with a compat wrapper codeQlAnnotationFromSymbolOwner() that uses
IrAnnotationImpl.fromSymbolOwner() in 2.4.0 (returning proper
IrAnnotation instances) and IrConstructorCallImpl.fromSymbolOwner()
in pre-2.4.0 versions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 18:12:45 +02:00
Anders Fugmann
9723044342 Kotlin 2.4.0: Fix value argument indexing in compat layer
In 2.4.0, IrMemberAccessExpression.arguments includes all parameters
(dispatch receiver, extension receiver, and regular value args). The
old getValueArgument/putValueArgument/valueArgumentsCount APIs indexed
only value arguments. Fix the compat layer to apply the correct offset
when translating between the old index-based API and the new unified
arguments list.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 17:30:40 +02:00
Anders Fugmann
e21bc4da05 Kotlin 2.4.0: Fix plugin service file to be version-conditional
The CompilerPluginRegistrar service file must only be included in the
2.4.0 jar. Older Kotlin versions (2.3.x and below) read this service
file and try to cast the class to CompilerPluginRegistrar, but the
older version extractor only implements ComponentRegistrar, causing a
ClassCastException at runtime.

For 2.4.0, the registrar implements both ComponentRegistrar (no-op, as
extensionArea was removed) and CompilerPluginRegistrar (actual
registration via ExtensionStorage).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 16:54:50 +02:00
Anders Fugmann
4a2f244ffa Kotlin: Add 2.4.0 API compatibility layer and plugin registration
- Add version-specific compatibility wrappers (v_2_4_0/IrCompat.kt) for
  removed APIs: valueParameters, extensionReceiverParameter, extensionReceiver,
  getValueArgument, putValueArgument, valueArgumentsCount, typeArgumentsCount,
  getTypeArgument, addAnnotations, setAnnotations, setDispatchReceiverParameter
- Add pre-2.4.0 pass-through implementations (v_1_8_0/IrCompat.kt)
- Migrate plugin registration from ComponentRegistrar to CompilerPluginRegistrar
  for 2.4.0 (v_2_4_0/Kotlin2ComponentRegistrar.kt)
- Add META-INF service file for CompilerPluginRegistrar
- Update all extractor source files to use codeQl* compat functions
- All versions (1.8.0 through 2.4.0) build successfully

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 15:25:35 +02:00
Anders Fugmann
ed9e160e89 Kotlin: Add 2.4.0 compiler jars and register version
Download kotlin-compiler-2.4.0.jar, kotlin-compiler-embeddable-2.4.0.jar,
and kotlin-stdlib-2.4.0.jar from Maven Central. Add 2.4.0 to the VERSIONS
list and update MODULE.bazel via bazel mod tidy.

The extractor does not yet compile against 2.4.0 due to removed APIs
(valueParameters, extensionReceiverParameter, getValueArgument, etc.).
Version-specific compatibility shims are needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 15:02:27 +02:00
Anders Fugmann
ed996ae48b Kotlin: Add support for Kotlin 2.4.0
Raise the acceptable version limit to 2.4.10 and update documentation
to reflect Kotlin 2.4.x support.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 12:58:52 +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
Jeroen Ketema
ab4a575243 Merge pull request #21899 from MathiasVP/use-new-prototype-extensionals
C++: Use the new `prototype`-related extensionals in MaD
2026-06-01 10:24:19 +02:00
Tom Hvitved
d2f474d998 Address review comments 2026-06-01 08:30:01 +02:00
Mathias Vorreiter Pedersen
22b08f1ea4 C++: Add a test with a kind of "partial function template" instantiation. 2026-05-31 12:47:31 +02:00
Owen Mansel-Chan
5e5a0437e1 Shared CFG: allow init stmts for IfStmt 2026-05-30 07:35:29 +01:00
Mathias Vorreiter Pedersen
e18448dd59 C++: Add more tests. 2026-05-29 18:22:13 +02:00
Henry Mercer
a16f1c555c Merge pull request #21912 from github/post-release-prep/codeql-cli-2.25.6
Post-release preparation for codeql-cli-2.25.6
2026-05-29 14:43:56 +01:00
Geoffrey White
43c1152634 Merge pull request #21905 from geoffw0/swiftflow2
Swift: Update the new metatype sinks
2026-05-29 14:18:45 +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
github-actions[bot]
cfb18c2477 Post-release preparation for codeql-cli-2.25.6 2026-05-29 12:04:35 +00:00
Anders Schack-Mulligen
4c31866910 Merge pull request #21867 from aschackmull/ruby/callable-body
Ruby: Split callable and its body into two AST nodes.
2026-05-29 10:16:19 +02:00
Tom Hvitved
09371339d7 Ruby: Adopt shared local name resolution library 2026-05-29 09:06:14 +02:00
Taus
6165623cbf Merge pull request #21724 from github/tausbn/python-add-self-validating-cfg-tests 2026-05-28 22:07:55 +02:00
Michael Nebel
2eac8890d3 Merge pull request #21893 from michaelnebel/cshar/updateroslyn
C#: Update Roslyn and other pinned depenencies.
2026-05-28 13:49:29 +02:00
Mathias Vorreiter Pedersen
2d581504f7 C++: Fix Copilot comments. 2026-05-28 13:34:18 +02:00
Mathias Vorreiter Pedersen
9f211cebd5 C++: Accept test changes. 2026-05-28 13:34:16 +02:00
Mathias Vorreiter Pedersen
8393b40b59 C++: Use the new extensionals to map template functions and classes to their fully templated versions. 2026-05-28 13:34:12 +02:00
Geoffrey White
f8ab76e1ba Swift: Update the new metatype sinks to not rely on name matching '.Type'. 2026-05-28 12:14:10 +01:00
Geoffrey White
34d4e9a8e2 Merge pull request #21898 from geoffw0/swiftflow
Swift: Extend swift/weak-sensitive-data-hashing, swift/weak-password-hashing sinks
2026-05-28 11:52:32 +01:00
Michael Nebel
ed8b9c29cc Merge pull request #21866 from michaelnebel/csharp/refreturnindexerproperty
C#: Property- and Indexer calls for ref return properties and indexers.
2026-05-28 12:31:17 +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
Asger F
17fe3e4e31 Merge pull request #21901 from asgerf/unified-fix-test
Unified: fix test output
2026-05-27 22:19:17 +02:00
Asger F
313500e581 Unified: update test outputs 2026-05-27 21:27:09 +02:00
Asger F
ad56ebd361 Unified: update test output 2026-05-27 21:25:32 +02:00
Asger F
6be9e2315d Merge pull request #21841 from github/tausbn/unified-swift-named-body-fields
Unified: Get rid of all `$children` fields
2026-05-27 21:25:11 +02:00
Geoffrey White
5c2488e304 Swift: Fix typo. 2026-05-27 16:29:48 +01:00
Geoffrey White
4fbea4ef95 Swift: Autoformat. 2026-05-27 16:28:21 +01:00
Taus
35faec3db1 Python: Address review comments
- Get rid of unnecessary parentheses
- Use call syntax in the relevant test
- Get rid of `dead(2)` annotation
2026-05-27 15:27:19 +00:00
Mathias Vorreiter Pedersen
5f54a8691d C++: Small cleanup. This has no effect on semantics. 2026-05-27 17:16:22 +02:00
Taus
41fd59c1c1 Unified: regenerate Ast.qll and dbscheme 2026-05-27 15:02:28 +00:00
Taus
d6e7e38e1c Unified: merge in main
Keeps our version of the conflicting files. They will be regenerated in
the next commit.
2026-05-27 15:01:03 +00:00
Jeroen Ketema
7723324687 Merge pull request #21896 from jketema/jketema/deprecated
C++: Remove deprecated code
2026-05-27 14:11:10 +02:00
Michael Nebel
d4c7b5b6fe C#: Update encoding of SBCS to UTF8 with BOM. 2026-05-27 14:01:34 +02:00
Michael Nebel
6b55f865cd C#: Update integration test expected output. 2026-05-27 13:24:45 +02:00
Jeroen Ketema
42c4d8a98b Merge pull request #21897 from jketema/jketema/missing-friend
C++: Update expected test results after extractor changes
2026-05-27 12:54:00 +02:00
Geoffrey White
f962eac914 Swift: Fill the simple gaps in modelling. 2026-05-27 11:20:00 +01:00
Geoffrey White
c6c3e1474c Swift: Add a few more test cases for simple missing models. 2026-05-27 11:15:28 +01:00
Geoffrey White
94e6ec6511 Swift: Widen the new sinks to cover more cases the MaD sinks are missing. 2026-05-27 10:34:12 +01:00
Geoffrey White
c902c75651 Swift: Add change note. 2026-05-27 10:33:42 +01:00
Geoffrey White
2b4ea18dfe Swift: Add a similar sink for password hashing as well. 2026-05-27 10:33:41 +01:00
Geoffrey White
98b7659cc1 Swift: Add a special case sink for weak sensitive data hashing sinks that are calls through a metatype. 2026-05-27 10:33:39 +01:00
Geoffrey White
d9c0b9ca31 Swift: Additional test cases for CryptoKit. 2026-05-27 10:33:37 +01:00
Geoffrey White
b44bca9ea7 Swift: Add HashFunction protocol and other realism to the CryptoKit test stubs (this is needed for new cases to work as intended). 2026-05-27 10:33:31 +01:00
Jeroen Ketema
e66b1e4beb Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-27 10:58:05 +02:00
Jeroen Ketema
362c48cc6d C++: Add change note 2026-05-27 10:44:44 +02:00
Jeroen Ketema
35364a087a C++: Update expected test results after extractor changes 2026-05-27 10:23:16 +02:00
Anders Schack-Mulligen
780591d42a Ruby: Remove spurious parent-child edges for Ruby::SimpleSymbol.
These treesitter nodes translate to multiple AstNodes, but we only want
those that are Stmts.
2026-05-27 10:06:15 +02:00
Anders Schack-Mulligen
3aa69823af Ruby: Skip BodyStmt in ErbDirective.getAChildStmt. 2026-05-27 10:06:14 +02:00
Asger F
f18cdcfec6 Merge pull request #21848 from asgerf/asgerf/swift-yeast
Unified: Add schema checking and corpus-style tests
2026-05-26 22:00:21 +02:00
Jeroen Ketema
7862922e5c C++: Remove deprecated code 2026-05-26 17:54:51 +02:00
Taus
fbc861e7a4 unified: Clarify grammar comment
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-26 16:19:02 +02:00
Michael Nebel
7f2fb2eb99 C#: Use the generic version of the associated implementation. 2026-05-26 15:59:25 +02:00
Michael Nebel
769b1957a5 C#: Update generated files. 2026-05-26 14:13:02 +02:00
Michael Nebel
26da373bd4 C#: Update Roslyn and other pinned dependencies. 2026-05-26 14:11:36 +02:00
Anders Schack-Mulligen
e07f45fff4 Ruby: Accept test changes. 2026-05-22 13:36:59 +02:00
Anders Schack-Mulligen
3adb7043e8 Ruby: Fix pre-existing bug. 2026-05-22 13:29:45 +02:00
Anders Schack-Mulligen
7dcd2d6ab6 Ruby: Adjust CFG to updated AST. 2026-05-22 11:06:15 +02:00
Anders Schack-Mulligen
b6c2915f24 Ruby: Split callable and its body into two AST nodes. 2026-05-22 11:06:14 +02:00
Michael Nebel
6825ccc74f C#: Add change-note. 2026-05-19 14:24:08 +02:00
Michael Nebel
c0273ae94f C#: Update other affected tests (including database quality). 2026-05-19 14:24:05 +02:00
Michael Nebel
1c01bb32d9 C#: Update test expected output. 2026-05-19 14:24:03 +02:00
Michael Nebel
c3bb5e8eff C#: Use ref return getters for properties/indexers in write contexts. 2026-05-19 14:24:00 +02:00
Michael Nebel
9d0d4e4912 C#: Add ref return info for accessors. 2026-05-19 14:23:57 +02:00
Michael Nebel
a2ac0ab7d5 C#: Add test case for indexer calls and update test expected for other files. 2026-05-19 14:23:55 +02:00
Michael Nebel
42aaae7cf3 C#: Add test case for property calls and update test expected for other files. 2026-05-19 14:23:52 +02:00
Anders Schack-Mulligen
cb0fc786c7 Ruby: Minor cleanup, Callable is a StmtSequence. 2026-05-18 13:05:14 +02:00
Taus
dd9c066c61 unified: Regenerate files 2026-05-13 14:24:12 +00:00
Taus
f4f85b58ca unified: Remove some pointless fields
All of these fields have contents that are uniquely determined by the
node they appear on, so they convey no information.
2026-05-13 14:22:06 +00:00
Taus
caef72b047 unified: Introduced named property_binding node
This groups together a bunch of related values that would otherwise be
impossible to match up correctly.
2026-05-13 13:54:21 +00:00
Taus
9787a8b072 unified: Group enum entries
Same as in the preceding commit.
2026-05-13 13:51:25 +00:00
Taus
c8f7c3d7f2 unified: Group more paired items
Same as in the preceding commit, these items do not make sense as
separate fields on the parent node, so we materialise (or create new)
intermediate nodes to group them together.
2026-05-13 13:49:30 +00:00
Taus
ea6f3a9568 unified: Encapsulate function parameters
The field representation would have made it difficult to figure out
which parameters correspond to which default values and attributes, so
instead we now encapsulate these in a new `function_parameter` node.
2026-05-13 13:20:58 +00:00
Taus
5d6dc5c3c3 unified: Clean up statements/block mess
Introduces (by making it named) a `block` node, and conversely makes
`statements` anonymous. This enables us to sensibly distinguish between
the "then" and "else" branch of an `if_statement`, which we were not
able to previously.
2026-05-13 13:06:34 +00:00
Asger F
554bdf14b2 Yeast: fix warning about unnecessary mutability 2026-05-13 11:19:51 +02:00
Asger F
b031e5b1f8 Unified: regenerate QL and make tests not crash
The output is not so interesting as the mapping removes most nodes from the current test file.

I added a name_expr.swift test so at least one NameExpr makes it through.
2026-05-13 10:48:43 +02:00
Asger F
7fa6c4e4a3 Unified: Update test output after rebasing on grammar changes
The branch was rebased on the grammar changes, but rewriting the history was too difficult, so I'm just updating the test output here.
2026-05-13 10:35:34 +02:00
Asger F
600a4969c9 Unified: Simplify concatenation of arguments 2026-05-13 10:35:33 +02:00
Asger F
55194dd757 Unified: Support for calls and member access 2026-05-13 10:35:31 +02:00
Asger F
cbe4c81ca6 Unified: add tuple_pattern and sequence_condition; refine if-let/guard mapping
ast_types.yml additions:
- tuple_pattern { element*: pattern } in the pattern supertype.
- sequence_condition { stmt*: stmt, condition: condition } in the
  condition supertype.

swift.rs:
- Map Swift tuple destructuring (e.g. `let (a, b) = pair`) to the new
  tuple_pattern instead of synthesizing an apply_pattern.
- if-let / guard-let: explicitly match the value_binding_pattern
  (the `let` keyword) and bind the source expression as the next
  condition child, so `let` no longer leaks into the output.
2026-05-13 10:35:29 +02:00
Asger F
3b7a53f678 yeast-macros: merge repeated field declarations and support repetition in field patterns
Two changes to parse_query_fields:

- Allow `field: (kind)* @cap` (repetition + optional capture) in field
  position, mirroring how it works for bare children.
- When the same field name is declared multiple times in a query (e.g.
  `condition: (foo) condition: (bar)`), merge them into a single
  ordered list of children rather than emitting duplicate field
  entries (which at runtime restart the iterator for the field and
  cause the second declaration to re-match from the first child).
2026-05-13 10:35:27 +02:00
Asger F
ccc1dd5d3e Unified: Add tuple_pattern 2026-05-13 10:35:26 +02:00
Asger F
a966dff76e Unified: Add more patterns and some fixes to the AST 2026-05-13 10:35:24 +02:00
Asger F
6b58482dfb Yeast: Fix text associated with synthesized nodes 2026-05-13 10:35:22 +02:00
Asger F
2307839050 Yeast: Change how patterns with repetition are parsed 2026-05-13 10:35:21 +02:00
Asger F
92838011dd Unified: Add some more AST nodes and rules 2026-05-13 10:35:19 +02:00
Asger F
5772ee4d9b YEAST: add NodeRef type, YeastDisplay trait, and source text storage
Introduce NodeRef as a typed wrapper around node arena IDs. Captures in
desugaring rules are now bound as NodeRef instead of raw usize, which
prevents accidental misuse and enables source-text-aware rendering.

Add the YeastDisplay trait as an alternative to Display: its
yeast_to_string method receives the Ast, allowing NodeRef to resolve to
the captured node's source text instead of printing a numeric ID.

Store the original source bytes in the Ast so that NodeContent::Range
values (from synthesized literal nodes) can be resolved back to text.

Update yeast-macros to emit NodeRef-typed capture bindings and use
Into::<usize>::into where raw IDs are needed. The #{expr} template
syntax now uses YeastDisplay instead of Display.

The effect is visible in the corpus tests: operator nodes now correctly
render as e.g. operator "+" instead of operator "3".

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:35:17 +02:00
Asger F
72b683d63c Unified: Add Swift corpus tests
Add corpus test cases for Swift covering closures, collections, control
flow, functions, literals, loops, operators, optionals/errors, types,
and variables. Update existing desugar.txt with raw parse sections.

Note: operator nodes currently render their node ID instead of the actual
operator text (e.g. operator "3" instead of operator "+"). This will be
fixed in the next commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:35:16 +02:00
Asger F
8a2a48d2dd Unified extractor: add AST schema, swift translation rules, and corpus framework
Add ast_types.yml defining the unified output AST schema with supertypes
(expr, stmt, condition, pattern) and named nodes (top_level, binary_expr,
name_expr, etc.).

Rewrite swift translation rules to map from tree-sitter Swift grammar to
the unified AST, using one-shot phase rules.

Update the generator to use the output AST schema for dbscheme/QL
generation, and normalize the extraction table prefix to 'unified'.

Improve the corpus test framework to include raw tree-sitter parse output,
type-error checking against the output schema, and better failure
reporting.

Regenerate Ast.qll, unified.dbscheme, and update BasicTest accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:35:14 +02:00
Asger F
5d0cb9e805 YEAST: fix one-shot rules for unnamed nodes and self-captures
One-shot desugaring rules now skip unnamed nodes (punctuation, keywords,
etc.) since rules are intended to target named nodes only.

Also prevent infinite recursion when a capture refers to the root node of
the matched tree (e.g. an @_ capture on the pattern root).

Additionally fix the swift.rs add_phase call to match the updated 3-arg
signature introduced by the one-shot phase kind commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:35:12 +02:00
Asger F
bb9e996cb6 Shared: Do not emit ReservedWord class when there are no unnamed tokens 2026-05-13 10:35:11 +02:00
Asger F
c3a9218dcf Yeast: Add one-shot phase kind 2026-05-13 10:35:09 +02:00
Asger F
a049850c51 Yeast: add type-checking errors in AST dump 2026-05-13 10:35:07 +02:00
Asger F
49f19092fb Yeast: add reachable_node_ids() 2026-05-13 10:35:05 +02:00
Asger F
f668b99d6d Unified: Add support for tree-sitter-style corpus tests
This adds tests consisting of source code and a printout of its rewritten AST.
2026-05-13 10:35:02 +02:00
Taus
bfe5aa8d42 unified: Regenerate files 2026-05-12 16:01:32 +00:00
Taus
52d72836f9 unified: Fix multiline_comment issue
This named node (which is in fact emitted by the scanner as an
`external`) was appearing as a child of `class_body` because of inlining
via `_class_member_separator`. This, in itself, appears to be somewhat
of a hack, to handle cases where a multiline comment signals the end of
a class member.

To fix this, we make the external node _unnamed_, but keep the `extras`
node _named_ (so we can still extract it from the parse tree), and we
add a new rule `multiline_comment` that mediates between the two. That
way, the use inside `_class_member_separator` can use the unnamed
variant, and no node is pushed into $children.
2026-05-12 15:59:18 +00:00
Taus
eb480d1de4 unified: Make parenthesized_type named
I'm not entirely happy about this solution, but it seemed to be the most
straightforward way of avoiding various kinds of token bleeding.
2026-05-12 15:38:29 +00:00
Taus
1ef557c972 Python: Address Copilot's comments 2026-05-12 15:27:14 +00:00
Taus
2eee2e50dc unified: clean up patterns
Mostly by materialising a bunch of (useful) intermediate nodes.
2026-05-12 15:23:26 +00:00
Taus
2010844b1e unified: Add fields to property_declaration
Not entirely sure about the `binding?` field on `pattern`, but it looks
like that might actually be useful.
2026-05-12 15:14:35 +00:00
Taus
406a02fa49 unified: Add fields to switch_entry
Of note: this involved un-inlining where_clause.
2026-05-12 15:09:02 +00:00
Taus
6e5e650b42 unified: Add fields for macro_declaration 2026-05-12 15:03:29 +00:00
Taus
eba9f35673 unified: Get rid of $children* on key_path_expression
Doing this involved materialising a lot of previously anonymous nodes,
and I'm not entirely sure it's the best solution, but the node types
look decent enough.
2026-05-12 15:01:10 +00:00
Taus
e1a0e204b1 unified: Promote enum_type_parameter to named and add fields 2026-05-12 14:55:43 +00:00
Taus
5e14a7574e unified: make compilation_condition named and add fields 2026-05-12 14:55:42 +00:00
Taus
6ff404a6d0 unified: More miscellaneous field additions 2026-05-12 14:50:01 +00:00
Taus
9902beddec unified: add proper fields for availability_condition 2026-05-12 14:47:58 +00:00
Taus
e6eac3784a unified: Consolidate fields in if_let_binding 2026-05-12 14:43:13 +00:00
Taus
5784ef22f6 unified: Unify more fields
Not entirely happy about the mixed nature of the `kind` filed (having
both tokens and the named node `throw_keyword` in there), but that's a
problem for a different time.
2026-05-12 14:40:17 +00:00
Taus
bc96ae6e47 unified: Add lambda and arguments fields 2026-05-12 14:29:23 +00:00
Taus
15d84b3e53 unified: More $children fixes
Some nodes with a single child (arguably redundant to do, but I think
it's nice to have the types be consistent), and also an instance of
ensuring that all branches of a `choice` expose consistent field names.
2026-05-12 14:15:36 +00:00
Taus
0499932ba0 unified: Fix fields in await_expression
This required a change in a different place, due to aliasing.
2026-05-12 14:10:38 +00:00
Taus
732cc7bee0 unified: Add fields to inheritance specifiers and calls 2026-05-12 14:07:58 +00:00
Taus
853a98842d unified: Regenerate files 2026-05-12 14:00:14 +00:00
Taus
d6ef467fba unified: Add more fields
A lot of changes, but for the most part these are just adding named
fields in places where they make sense.

After this, there are still ~20 instances of unnamed children appearing.
2026-05-12 13:59:56 +00:00
Taus
c75d819a92 unified: Add effect field
I ended up also aliasing `_async_keyword` to a named node to make it
more consistent with the other node kinds that can be in this field (as
it would be awkward to have two named types and a token here).

Elsewhere in the node types, we'll still have `async?: "async"`, and I
think that's okay.
2026-05-12 13:46:25 +00:00
Taus
75c07996f3 unified: regenerate files 2026-05-12 12:57:26 +00:00
Taus
9dddd93460 unified: add field declarations for statements and members
Part 1 of N of "getting rid of $children" in node-types.yml

Note: in one of the cases the affected node still has the $children
field present. This is because there's some weirdness about recording
multiline comments as class member separators that I did not want to
figure out how to address right now.
2026-05-12 12:57:26 +00:00
Taus
f5c3b63a4a Python: Add ConsecutiveTimestamps test
This one is potentially a bit iffy -- it checks for a very powerful
property (that implies many of the other queries), but as the test
results show, it can produce false positives when there is in fact no
problem. We may want to get rid of it entirely, if it becomes too noisy.
2026-05-12 12:54:26 +00:00
Taus
c30d6ae3aa Python: Add NeverReachable test
This looks for nodes annotated with `t[never]` in the test that are
reachable in the CFG. This should not happen (it messes with various
queries, e.g. the "mixed returns" query), but the test shows that in a
few particular cases (involving the `match` statement where all cases
contain `return`s), we _do_ have reachable nodes that shouldn't be.
2026-05-12 12:54:26 +00:00
Taus
fc2bc26f36 Python: Add BasicBlockOrdering test
This one demonstrates a bug in the current CFG. In a dictionary
comprehension `{k: v for k, v in d.items()}`, we evaluate the value
before the key, which is incorrect. (A fix for this bug has been
implemented in a separate PR.)
2026-05-12 12:54:25 +00:00
Taus
3a979ac2f8 Python: Add some CFG-validation queries
These use the annotated, self-verifying test files to check various
consistency requirements.

Some of these may be expressing the same thing in different ways, but
it's fairly cheap to keep them around, so I have not attempted to
produce a minimal set of queries for this.
2026-05-12 12:54:25 +00:00
Taus
71cd5be513 Python: Add self-validating CFG tests
These tests consist of various Python constructions (hopefully a
somewhat comprehensive set) with specific timestamp annotations
scattered throughout. When the tests are run using the Python 3
interpreter, these annotations are checked and compared to the "current
timestamp" to see that they are in agreement. This is what makes the
tests "self-validating".

There are a few different kinds of annotations: the basic `t[4]` style
(meaning this is executed at timestamp 4), the `t[dead(4)]` variant
(meaning this _would_ happen at timestamp 4, but it is in a dead
branch), and `t[never]` (meaning this is never executed at all).

In addition to this, there is a query, MissingAnnotations, which checks
whether we have applied these annotations maximally. Many expression
nodes are not actually annotatable, so there is a sizeable list of
excluded nodes for that query.
2026-05-12 12:42:29 +00: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
343 changed files with 32128 additions and 11469 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

@@ -1,5 +1,5 @@
name: codeql/actions-all name: codeql/actions-all
version: 0.4.37 version: 0.4.38-dev
library: true library: true
warnOnImplicitThis: true warnOnImplicitThis: true
dependencies: dependencies:

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries name: codeql/actions-queries
version: 0.6.29 version: 0.6.30-dev
library: false library: false
warnOnImplicitThis: true warnOnImplicitThis: true
groups: [actions, queries] groups: [actions, queries]

View File

@@ -30,8 +30,6 @@ class Options extends string {
predicate overrideReturnsNull(Call call) { predicate overrideReturnsNull(Call call) {
// Used in CVS: // Used in CVS:
call.(FunctionCall).getTarget().hasGlobalName("Xstrdup") call.(FunctionCall).getTarget().hasGlobalName("Xstrdup")
or
CustomOptions::overrideReturnsNull(call) // old Options.qll
} }
/** /**
@@ -45,8 +43,6 @@ class Options extends string {
// Used in CVS: // Used in CVS:
call.(FunctionCall).getTarget().hasGlobalName("Xstrdup") and call.(FunctionCall).getTarget().hasGlobalName("Xstrdup") and
nullValue(call.getArgument(0)) nullValue(call.getArgument(0))
or
CustomOptions::returnsNull(call) // old Options.qll
} }
/** /**
@@ -65,8 +61,6 @@ class Options extends string {
f.hasGlobalOrStdName([ f.hasGlobalOrStdName([
"exit", "_exit", "_Exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" "exit", "_exit", "_Exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable"
]) ])
or
CustomOptions::exits(f) // old Options.qll
} }
/** /**
@@ -79,8 +73,7 @@ class Options extends string {
* runtime, the program's behavior is undefined) * runtime, the program's behavior is undefined)
*/ */
predicate exprExits(Expr e) { predicate exprExits(Expr e) {
e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 or e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0
CustomOptions::exprExits(e) // old Options.qll
} }
/** /**
@@ -88,10 +81,7 @@ class Options extends string {
* *
* By default holds only for `fgets`. * By default holds only for `fgets`.
*/ */
predicate alwaysCheckReturnValue(Function f) { predicate alwaysCheckReturnValue(Function f) { f.hasGlobalOrStdName("fgets") }
f.hasGlobalOrStdName("fgets") or
CustomOptions::alwaysCheckReturnValue(f) // old Options.qll
}
/** /**
* Holds if it is reasonable to ignore the return value of function * Holds if it is reasonable to ignore the return value of function
@@ -107,8 +97,6 @@ class Options extends string {
// common way of sleeping using select: // common way of sleeping using select:
fc.getTarget().hasGlobalName("select") and fc.getTarget().hasGlobalName("select") and
fc.getArgument(0).getValue() = "0" fc.getArgument(0).getValue() = "0"
or
CustomOptions::okToIgnoreReturnValue(fc) // old Options.qll
} }
} }

View File

@@ -98,57 +98,3 @@ class CustomMutexType extends MutexType {
*/ */
override predicate unlockAccess(FunctionCall fc, Expr arg) { none() } override predicate unlockAccess(FunctionCall fc, Expr arg) { none() }
} }
/**
* DEPRECATED: customize `CustomOptions.overrideReturnsNull` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate overrideReturnsNull(Call call) { none() }
/**
* DEPRECATED: customize `CustomOptions.returnsNull` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate returnsNull(Call call) { none() }
/**
* DEPRECATED: customize `CustomOptions.exits` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate exits(Function f) { none() }
/**
* DEPRECATED: customize `CustomOptions.exprExits` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate exprExits(Expr e) { none() }
/**
* DEPRECATED: customize `CustomOptions.alwaysCheckReturnValue` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate alwaysCheckReturnValue(Function f) { none() }
/**
* DEPRECATED: customize `CustomOptions.okToIgnoreReturnValue` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate okToIgnoreReturnValue(FunctionCall fc) { none() }

View File

@@ -0,0 +1,15 @@
---
category: breaking
---
* Removed the deprecated `overrideReturnsNull` predicate from `Options.qll`. Use `CustomOptions.overrideReturnsNull` instead.
* Removed the deprecated `returnsNull` predicate from `Options.qll`. Use `CustomOptions.returnsNull` instead.
* Removed the deprecated `exits` predicate from `Options.qll`. Use `CustomOptions.exits` instead.
* Removed the deprecated `exprExits` predicate from `Options.qll`. Use `CustomOptions.exprExits` instead.
* Removed the deprecated `alwaysCheckReturnValue` predicate from `Options.qll`. Use `CustomOptions.alwaysCheckReturnValue` instead.
* Removed the deprecated `okToIgnoreReturnValue` predicate from `Options.qll`. Use `CustomOptions.okToIgnoreReturnValue` instead.
* Removed the deprecated `semmle.code.cpp.Member`. Import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly.
* Removed the deprecated `UnknownDefaultLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `UnknownExprLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `UnknownStmtLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `TemplateParameter` class. Use `TypeTemplateParameter` instead.
* Support for class resolution across link targets has been removed for databases which were created with CodeQL versions before 1.23.0.

View File

@@ -32,7 +32,6 @@ import semmle.code.cpp.Class
import semmle.code.cpp.Struct import semmle.code.cpp.Struct
import semmle.code.cpp.Union import semmle.code.cpp.Union
import semmle.code.cpp.Enum import semmle.code.cpp.Enum
import semmle.code.cpp.Member
import semmle.code.cpp.Field import semmle.code.cpp.Field
import semmle.code.cpp.Function import semmle.code.cpp.Function
import semmle.code.cpp.MemberFunction import semmle.code.cpp.MemberFunction

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 10.2.0 version: 10.2.1-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -148,28 +148,3 @@ class UnknownLocation extends Location {
this.getFile().getAbsolutePath() = "" and locations_default(this, _, 0, 0, 0, 0) this.getFile().getAbsolutePath() = "" and locations_default(this, _, 0, 0, 0, 0)
} }
} }
/**
* A dummy location which is used when something doesn't have a location in
* the source code but needs to have a `Location` associated with it.
*
* DEPRECATED: use `UnknownLocation`
*/
deprecated class UnknownDefaultLocation extends UnknownLocation { }
/**
* A dummy location which is used when an expression doesn't have a
* location in the source code but needs to have a `Location` associated
* with it.
*
* DEPRECATED: use `UnknownLocation`
*/
deprecated class UnknownExprLocation extends UnknownLocation { }
/**
* A dummy location which is used when a statement doesn't have a location
* in the source code but needs to have a `Location` associated with it.
*
* DEPRECATED: use `UnknownLocation`
*/
deprecated class UnknownStmtLocation extends UnknownLocation { }

View File

@@ -1,6 +0,0 @@
/**
* DEPRECATED: import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly as required.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Type

View File

@@ -35,13 +35,6 @@ class NonTypeTemplateParameter extends Literal, TemplateParameterImpl {
override string getAPrimaryQlClass() { result = "NonTypeTemplateParameter" } override string getAPrimaryQlClass() { result = "NonTypeTemplateParameter" }
} }
/**
* A C++ `typename` (or `class`) template parameter.
*
* DEPRECATED: Use `TypeTemplateParameter` instead.
*/
deprecated class TemplateParameter = TypeTemplateParameter;
/** /**
* A C++ `typename` (or `class`) template parameter. * A C++ `typename` (or `class`) template parameter.
* *

View File

@@ -276,6 +276,45 @@ private predicate isClassConstructedFrom(Class c, Class templateClass) {
not c.isConstructedFrom(_) and c = templateClass not c.isConstructedFrom(_) and c = templateClass
} }
/** Gets the fully templated version of `c`. */
private Class getFullyTemplatedClassOld(Class c) {
not c.isFromUninstantiatedTemplate(_) and
isClassConstructedFrom(c, result)
}
private TemplateClass getOriginalClassTemplate(TemplateClass tc) {
result = tc.getOriginalTemplate()
or
not exists(tc.getOriginalTemplate()) and
result = tc
}
/** Gets the fully templated version of `c`. */
private Class getFullyTemplatedClassNew(Class c) {
not c.isFromUninstantiatedTemplate(_) and
exists(Class mid |
c.isConstructedFrom(mid)
or
not c.isConstructedFrom(_) and c = mid
|
result = getOriginalClassTemplate(mid)
or
not mid instanceof TemplateClass and mid = result
)
}
/** Gets the fully templated version of `c`. */
private Class getFullyTemplatedClass(Class c) {
// The `Class::getOriginalTemplate` predicate was introduced in CodeQL
// version 2.25.6 and the upgrade script leaves the
// `class_template_generated_from` extensionals empty if the database
// was generated with an older extractor. So we use the old implementation
// if the `class_template_generated_from` extensional is empty.
if class_template_generated_from(_, _)
then result = getFullyTemplatedClassNew(c)
else result = getFullyTemplatedClassOld(c)
}
/** /**
* Holds if `f` is an instantiation of a function template `templateFunc`, or * Holds if `f` is an instantiation of a function template `templateFunc`, or
* holds with `f = templateFunc` if `f` is not an instantiation of any function * holds with `f = templateFunc` if `f` is not an instantiation of any function
@@ -292,7 +331,7 @@ private predicate isFunctionConstructedFrom(Function f, Function templateFunc) {
} }
/** Gets the fully templated version of `f`. */ /** Gets the fully templated version of `f`. */
Function getFullyTemplatedFunction(Function f) { private Function getFullyTemplatedFunctionOld(Function f) {
not f.isFromUninstantiatedTemplate(_) and not f.isFromUninstantiatedTemplate(_) and
( (
exists(Class c, Class templateClass, int i | exists(Class c, Class templateClass, int i |
@@ -306,13 +345,46 @@ Function getFullyTemplatedFunction(Function f) {
) )
} }
private TemplateFunction getOriginalFunctionTemplate(TemplateFunction tf) {
result = tf.getOriginalTemplate()
or
not exists(tf.getOriginalTemplate()) and
result = tf
}
/** Gets the fully templated version of `f`. */
private Function getFullyTemplatedFunctionNew(Function f) {
not f.isFromUninstantiatedTemplate(_) and
exists(Function mid |
f.isConstructedFrom(mid)
or
not f.isConstructedFrom(_) and f = mid
|
result = getOriginalFunctionTemplate(mid)
or
not mid instanceof TemplateFunction and mid = result
)
}
/** Gets the fully templated version of `f`. */
Function getFullyTemplatedFunction(Function f) {
// The `Function::getOriginalTemplate` predicate was introduced in CodeQL
// version 2.25.6 and the upgrade script leaves the
// `function_template_generated_from` extensionals empty if the database
// was generated with an older extractor. So we use the old implementation
// if the `function_template_generated_from` extensional is empty.
if function_template_generated_from(_, _)
then result = getFullyTemplatedFunctionNew(f)
else result = getFullyTemplatedFunctionOld(f)
}
/** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */ /** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */
bindingset[s, t] bindingset[s, t]
private string withConst(string s, Type t) { private string withConst(string s, Type t) {
if t.isConst() then result = "const " + s else result = s if t.isConst() then result = "const " + s else result = s
} }
/** Prefixes `volatile` to `s` if `t` is const, or returns `s` otherwise. */ /** Prefixes `volatile` to `s` if `t` is volatile, or returns `s` otherwise. */
bindingset[s, t] bindingset[s, t]
private string withVolatile(string s, Type t) { private string withVolatile(string s, Type t) {
if t.isVolatile() then result = "volatile " + s else result = s if t.isVolatile() then result = "volatile " + s else result = s
@@ -490,7 +562,7 @@ pragma[nomagic]
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) { private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
// If there is a declaring type then we start by expanding the function templates // If there is a declaring type then we start by expanding the function templates
exists(Class template | exists(Class template |
isClassConstructedFrom(f.getDeclaringType(), template) and template = getFullyTemplatedClass(f.getDeclaringType()) and
remaining = getNumberOfSupportedClassTemplateArguments(template) and remaining = getNumberOfSupportedClassTemplateArguments(template) and
result = getTypeNameWithoutFunctionTemplates(f, n, 0) result = getTypeNameWithoutFunctionTemplates(f, n, 0)
) )
@@ -502,7 +574,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
or or
exists(string mid, TypeTemplateParameter tp, Class template | exists(string mid, TypeTemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
isClassConstructedFrom(f.getDeclaringType(), template) and template = getFullyTemplatedClass(f.getDeclaringType()) and
tp = getSupportedClassTemplateArgument(template, remaining) tp = getSupportedClassTemplateArgument(template, remaining)
| |
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString()) result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())

View File

@@ -1,59 +1,5 @@
import semmle.code.cpp.Type import semmle.code.cpp.Type
/** For upgraded databases without mangled name info. */
pragma[noinline]
private string getTopLevelClassName(@usertype c) {
not mangled_name(_, _, _) and
isClass(c) and
usertypes(c, result, _) and
not namespacembrs(_, c) and // not in a namespace
not member(_, _, c) and // not in some structure
not class_instantiation(c, _) // not a template instantiation
}
/**
* For upgraded databases without mangled name info.
* Holds if `d` is a unique complete class named `name`.
*/
pragma[noinline]
private predicate existsCompleteWithName(string name, @usertype d) {
not mangled_name(_, _, _) and
is_complete(d) and
name = getTopLevelClassName(d) and
onlyOneCompleteClassExistsWithName(name)
}
/** For upgraded databases without mangled name info. */
pragma[noinline]
private predicate onlyOneCompleteClassExistsWithName(string name) {
not mangled_name(_, _, _) and
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
}
/**
* For upgraded databases without mangled name info.
* Holds if `c` is an incomplete class named `name`.
*/
pragma[noinline]
private predicate existsIncompleteWithName(string name, @usertype c) {
not mangled_name(_, _, _) and
not is_complete(c) and
name = getTopLevelClassName(c)
}
/**
* For upgraded databases without mangled name info.
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
* with the same name.
*/
private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
not mangled_name(_, _, _) and
exists(string name |
existsIncompleteWithName(name, c) and
existsCompleteWithName(name, d)
)
}
pragma[noinline] pragma[noinline]
private @mangledname getClassMangledName(@usertype c) { private @mangledname getClassMangledName(@usertype c) {
isClass(c) and isClass(c) and
@@ -103,10 +49,7 @@ private module Cached {
@usertype resolveClass(@usertype c) { @usertype resolveClass(@usertype c) {
hasCompleteTwin(c, result) hasCompleteTwin(c, result)
or or
oldHasCompleteTwin(c, result)
or
not hasCompleteTwin(c, _) and not hasCompleteTwin(c, _) and
not oldHasCompleteTwin(c, _) and
result = c result = c
} }

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 1.6.4 version: 1.6.5-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -51,13 +51,16 @@ models
| 50 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated | | 50 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 51 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual | | 51 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 52 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual | | 52 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 53 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual | | 53 | Summary: ; TemplateClass1; true; templateFunction2<U,V>; (U,V); ; Argument[1]; ReturnValue; value; manual |
| 54 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual | | 54 | Summary: ; TemplateClass1<T>; false; templateFunction<U>; (T,U); ; Argument[0]; ReturnValue; value; manual |
| 55 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual | | 55 | Summary: ; TemplateClass2<T,U>; true; function; (U,T); ; Argument[1]; ReturnValue; value; manual |
| 56 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual | | 56 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 57 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual | | 57 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
| 58 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
| 59 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
| 60 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
edges edges
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:57 | | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:60 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:32 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:32 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:32 Sink:MaD:2 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:32 Sink:MaD:2 |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction | | asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
@@ -66,24 +69,24 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | | | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:57 | | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:60 |
| azure.cpp:62:10:62:14 | [summary param] this in Value | azure.cpp:62:10:62:14 | [summary] to write: ReturnValue[*] in Value | provenance | MaD:56 | | azure.cpp:62:10:62:14 | [summary param] this in Value | azure.cpp:62:10:62:14 | [summary] to write: ReturnValue[*] in Value | provenance | MaD:59 |
| azure.cpp:113:16:113:19 | [summary param] this in Read | azure.cpp:113:16:113:19 | [summary param] *0 in Read [Return] | provenance | MaD:53 | | azure.cpp:113:16:113:19 | [summary param] this in Read | azure.cpp:113:16:113:19 | [summary param] *0 in Read [Return] | provenance | MaD:56 |
| azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | azure.cpp:114:16:114:26 | [summary param] *0 in ReadToCount [Return] | provenance | MaD:54 | | azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | azure.cpp:114:16:114:26 | [summary param] *0 in ReadToCount [Return] | provenance | MaD:57 |
| azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | provenance | MaD:55 | | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | provenance | MaD:58 |
| azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue in ReadToEnd [element] | provenance | | | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue in ReadToEnd [element] | provenance | |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:253:48:253:60 | *call to GetBodyStream | provenance | Src:MaD:29 | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:253:48:253:60 | *call to GetBodyStream | provenance | Src:MaD:29 |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | |
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | | | azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | |
| azure.cpp:257:5:257:8 | *resp | azure.cpp:113:16:113:19 | [summary param] this in Read | provenance | | | azure.cpp:257:5:257:8 | *resp | azure.cpp:113:16:113:19 | [summary param] this in Read | provenance | |
| azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:53 | | azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:56 |
| azure.cpp:257:16:257:21 | Read output argument | azure.cpp:258:10:258:16 | * ... | provenance | | | azure.cpp:257:16:257:21 | Read output argument | azure.cpp:258:10:258:16 | * ... | provenance | |
| azure.cpp:262:5:262:8 | *resp | azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | provenance | | | azure.cpp:262:5:262:8 | *resp | azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | provenance | |
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:54 | | azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:57 |
| azure.cpp:262:23:262:28 | ReadToCount output argument | azure.cpp:263:10:263:16 | * ... | provenance | | | azure.cpp:262:23:262:28 | ReadToCount output argument | azure.cpp:263:10:263:16 | * ... | provenance | |
| azure.cpp:266:38:266:41 | *resp | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | provenance | | | azure.cpp:266:38:266:41 | *resp | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | provenance | |
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:55 | | azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:58 |
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | | | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | |
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:267:10:267:12 | vec [element] | provenance | | | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:267:10:267:12 | vec [element] | provenance | |
| azure.cpp:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | | | azure.cpp:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | |
@@ -100,11 +103,11 @@ edges
| azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | provenance | Src:MaD:26 | | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | provenance | Src:MaD:26 |
| azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:282:21:282:23 | *call to get | provenance | | | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:282:21:282:23 | *call to get | provenance | |
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | provenance | | | azure.cpp:282:21:282:23 | *call to get | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | provenance | |
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:55 | | azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:58 |
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:10:282:38 | call to ReadToEnd | provenance | | | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:10:282:38 | call to ReadToEnd | provenance | |
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | | | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | |
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:62:10:62:14 | [summary param] this in Value | provenance | | | azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:62:10:62:14 | [summary param] this in Value | provenance | |
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:56 | | azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:59 |
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:24:289:56 | call to GetHeader | provenance | | | azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:24:289:56 | call to GetHeader | provenance | |
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:32:289:40 | call to GetHeader | provenance | Src:MaD:30 | | azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:32:289:40 | call to GetHeader | provenance | Src:MaD:30 |
| azure.cpp:289:63:289:65 | call to Value | azure.cpp:289:63:289:65 | call to Value | provenance | | | azure.cpp:289:63:289:65 | call to Value | azure.cpp:289:63:289:65 | call to Value | provenance | |
@@ -180,6 +183,39 @@ edges
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 | | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 |
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | | test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | |
| test.cpp:118:44:118:44 | *x | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | MaD:48 | | test.cpp:118:44:118:44 | *x | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | MaD:48 |
| test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | test.cpp:125:5:125:20 | [summary] to write: ReturnValue in templateFunction | provenance | MaD:54 |
| test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | test.cpp:128:5:128:21 | [summary] to write: ReturnValue in templateFunction2 | provenance | MaD:53 |
| test.cpp:133:10:133:18 | call to ymlSource | test.cpp:133:10:133:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:133:10:133:18 | call to ymlSource | test.cpp:134:45:134:45 | x | provenance | |
| test.cpp:134:13:134:43 | call to templateFunction | test.cpp:134:13:134:43 | call to templateFunction | provenance | |
| test.cpp:134:13:134:43 | call to templateFunction | test.cpp:135:10:135:10 | y | provenance | Sink:MaD:1 |
| test.cpp:134:45:134:45 | x | test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | provenance | |
| test.cpp:134:45:134:45 | x | test.cpp:134:13:134:43 | call to templateFunction | provenance | MaD:54 |
| test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | provenance | MaD:55 |
| test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | provenance | MaD:55 |
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:146:10:146:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:148:26:148:26 | x | provenance | |
| test.cpp:148:10:148:27 | call to function | test.cpp:148:10:148:27 | call to function | provenance | |
| test.cpp:148:10:148:27 | call to function | test.cpp:149:10:149:10 | z | provenance | Sink:MaD:1 |
| test.cpp:148:26:148:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | provenance | |
| test.cpp:148:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:55 |
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:155:10:155:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:157:26:157:26 | x | provenance | |
| test.cpp:157:13:157:20 | call to function | test.cpp:157:13:157:20 | call to function | provenance | |
| test.cpp:157:13:157:20 | call to function | test.cpp:158:10:158:10 | z | provenance | Sink:MaD:1 |
| test.cpp:157:26:157:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | provenance | |
| test.cpp:157:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:55 |
| test.cpp:164:34:164:34 | x | test.cpp:165:69:165:69 | x | provenance | |
| test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:164:7:164:7 | *templateFunction3 | provenance | |
| test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | |
| test.cpp:165:69:165:69 | x | test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | provenance | |
| test.cpp:165:69:165:69 | x | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | MaD:53 |
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:170:10:170:18 | call to ymlSource | provenance | Src:MaD:25 |
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:172:51:172:51 | x | provenance | |
| test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | |
| test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:173:10:173:10 | y | provenance | Sink:MaD:1 |
| test.cpp:172:51:172:51 | x | test.cpp:164:34:164:34 | x | provenance | |
| test.cpp:172:51:172:51 | x | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | MaD:53 |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:33 | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:33 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
@@ -483,6 +519,43 @@ nodes
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate |
| test.cpp:118:44:118:44 | *x | semmle.label | *x | | test.cpp:118:44:118:44 | *x | semmle.label | *x |
| test.cpp:119:10:119:11 | y2 | semmle.label | y2 | | test.cpp:119:10:119:11 | y2 | semmle.label | y2 |
| test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | semmle.label | [summary param] 0 in templateFunction |
| test.cpp:125:5:125:20 | [summary] to write: ReturnValue in templateFunction | semmle.label | [summary] to write: ReturnValue in templateFunction |
| test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | semmle.label | [summary param] 1 in templateFunction2 |
| test.cpp:128:5:128:21 | [summary] to write: ReturnValue in templateFunction2 | semmle.label | [summary] to write: ReturnValue in templateFunction2 |
| test.cpp:133:10:133:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:133:10:133:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:134:13:134:43 | call to templateFunction | semmle.label | call to templateFunction |
| test.cpp:134:13:134:43 | call to templateFunction | semmle.label | call to templateFunction |
| test.cpp:134:45:134:45 | x | semmle.label | x |
| test.cpp:135:10:135:10 | y | semmle.label | y |
| test.cpp:140:4:140:11 | [summary param] 1 in function | semmle.label | [summary param] 1 in function |
| test.cpp:140:4:140:11 | [summary param] 1 in function | semmle.label | [summary param] 1 in function |
| test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | semmle.label | [summary] to write: ReturnValue in function |
| test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | semmle.label | [summary] to write: ReturnValue in function |
| test.cpp:146:10:146:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:146:10:146:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:148:10:148:27 | call to function | semmle.label | call to function |
| test.cpp:148:10:148:27 | call to function | semmle.label | call to function |
| test.cpp:148:26:148:26 | x | semmle.label | x |
| test.cpp:149:10:149:10 | z | semmle.label | z |
| test.cpp:155:10:155:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:155:10:155:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:157:13:157:20 | call to function | semmle.label | call to function |
| test.cpp:157:13:157:20 | call to function | semmle.label | call to function |
| test.cpp:157:26:157:26 | x | semmle.label | x |
| test.cpp:158:10:158:10 | z | semmle.label | z |
| test.cpp:164:7:164:7 | *templateFunction3 | semmle.label | *templateFunction3 |
| test.cpp:164:34:164:34 | x | semmle.label | x |
| test.cpp:165:12:165:64 | call to templateFunction2 | semmle.label | call to templateFunction2 |
| test.cpp:165:12:165:64 | call to templateFunction2 | semmle.label | call to templateFunction2 |
| test.cpp:165:69:165:69 | x | semmle.label | x |
| test.cpp:170:10:170:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:170:10:170:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:172:13:172:44 | call to templateFunction3 | semmle.label | call to templateFunction3 |
| test.cpp:172:13:172:44 | call to templateFunction3 | semmle.label | call to templateFunction3 |
| test.cpp:172:51:172:51 | x | semmle.label | x |
| test.cpp:173:10:173:10 | y | semmle.label | y |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA | | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
@@ -688,6 +761,11 @@ subpaths
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | | test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | | test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | | test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate |
| test.cpp:134:45:134:45 | x | test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | test.cpp:125:5:125:20 | [summary] to write: ReturnValue in templateFunction | test.cpp:134:13:134:43 | call to templateFunction |
| test.cpp:148:26:148:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | test.cpp:148:10:148:27 | call to function |
| test.cpp:157:26:157:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | test.cpp:157:13:157:20 | call to function |
| test.cpp:165:69:165:69 | x | test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | test.cpp:128:5:128:21 | [summary] to write: ReturnValue in templateFunction2 | test.cpp:165:12:165:64 | call to templateFunction2 |
| test.cpp:172:51:172:51 | x | test.cpp:164:34:164:34 | x | test.cpp:164:7:164:7 | *templateFunction3 | test.cpp:172:13:172:44 | call to templateFunction3 |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | | windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | | windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument |
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument | | windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument |

View File

@@ -19,3 +19,6 @@ extensions:
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"] - ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
- ["", "", False, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"] - ["", "", False, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"]
- ["", "TemplateClass1<T>", False, "templateFunction<U>", "(T,U)", "", "Argument[0]", "ReturnValue", "value", "manual"]
- ["", "TemplateClass1", True, "templateFunction2<U,V>", "(U,V)", "", "Argument[1]", "ReturnValue", "value", "manual"]
- ["", "TemplateClass2<T,U>", True, "function", "(U,T)", "", "Argument[1]", "ReturnValue", "value", "manual"]

View File

@@ -15,3 +15,7 @@
| test.cpp:89:11:89:11 | y | test-sink | | test.cpp:89:11:89:11 | y | test-sink |
| test.cpp:116:10:116:11 | y1 | test-sink | | test.cpp:116:10:116:11 | y1 | test-sink |
| test.cpp:119:10:119:11 | y2 | test-sink | | test.cpp:119:10:119:11 | y2 | test-sink |
| test.cpp:135:10:135:10 | y | test-sink |
| test.cpp:149:10:149:10 | z | test-sink |
| test.cpp:158:10:158:10 | z | test-sink |
| test.cpp:173:10:173:10 | y | test-sink |

View File

@@ -9,6 +9,10 @@
| test.cpp:56:8:56:16 | call to ymlSource | local | | test.cpp:56:8:56:16 | call to ymlSource | local |
| test.cpp:94:10:94:18 | call to ymlSource | local | | test.cpp:94:10:94:18 | call to ymlSource | local |
| test.cpp:114:10:114:18 | call to ymlSource | local | | test.cpp:114:10:114:18 | call to ymlSource | local |
| test.cpp:133:10:133:18 | call to ymlSource | local |
| test.cpp:146:10:146:18 | call to ymlSource | local |
| test.cpp:155:10:155:18 | call to ymlSource | local |
| test.cpp:170:10:170:18 | call to ymlSource | local |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local | | windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local | | windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |

View File

@@ -118,3 +118,57 @@ void test_callWithNonTypeTemplate() {
int y2 = callWithNonTypeTemplate<int, 10>(x); int y2 = callWithNonTypeTemplate<int, 10>(x);
ymlSink(y2); // $ ir ymlSink(y2); // $ ir
} }
template<class T>
struct TemplateClass1 {
template<class U>
U templateFunction(T, U);
template<class U, class V>
V templateFunction2(U, V);
};
void test_template_function_in_template_class() {
TemplateClass1<int> b;
int x = ymlSource();
auto y = b.templateFunction<unsigned long>(x, 0UL);
ymlSink(y); // $ ir
}
template<class S, class T>
struct TemplateClass2 {
T function(T, S);
};
template<class V> using PartialInstantiationOfTemplateClass2 = TemplateClass2<int, V>;
void test_partial_class_instantiation() {
int x = ymlSource();
PartialInstantiationOfTemplateClass2<unsigned long> y;
int z = y.function(0UL, x);
ymlSink(z); // $ ir
}
template<class V> struct DeriveFromFromPartialTemplateInstantiation : TemplateClass2<int, V> { };
void test_inheritance() {
int x = ymlSource();
DeriveFromFromPartialTemplateInstantiation<long> y;
auto z = y.function(0L, x);
ymlSink(z); // $ ir
}
template<class T>
struct Class1 : TemplateClass1<T> {
template<class U>
int templateFunction3(U u, int x) {
return TemplateClass1<T>::template templateFunction2<U, int>(u, x);
}
};
void test_class1() {
int x = ymlSource();
Class1<int> c;
auto y = c.templateFunction3<unsigned long>(0UL, x);
ymlSink(y); // $ ir
}

View File

@@ -27383,54 +27383,55 @@ getParameterTypeName
| stl.h:91:24:91:33 | operator++ | 0 | int | | stl.h:91:24:91:33 | operator++ | 0 | int |
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & | | stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & | | stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
| stl.h:148:3:148:14 | basic_string | 0 | const class:2 & | | stl.h:147:12:147:23 | basic_string | 0 | const class:2 & |
| stl.h:149:33:149:44 | basic_string | 0 | const class:0 * | | stl.h:148:3:148:14 | basic_string | 0 | const class:0 * |
| stl.h:149:33:149:44 | basic_string | 1 | const class:2 & | | stl.h:148:3:148:14 | basic_string | 1 | const class:2 & |
| stl.h:151:16:151:20 | c_str | 0 | func:0 | | stl.h:149:33:149:44 | basic_string | 0 | func:0 |
| stl.h:151:16:151:20 | c_str | 1 | func:0 | | stl.h:149:33:149:44 | basic_string | 1 | func:0 |
| stl.h:151:16:151:20 | c_str | 2 | const class:2 & | | stl.h:149:33:149:44 | basic_string | 2 | const class:2 & |
| stl.h:165:8:165:16 | push_back | 0 | class:0 |
| stl.h:173:13:173:22 | operator[] | 0 | size_type | | stl.h:173:13:173:22 | operator[] | 0 | size_type |
| stl.h:175:13:175:14 | at | 0 | size_type | | stl.h:175:13:175:14 | at | 0 | size_type |
| stl.h:176:35:176:44 | operator+= | 0 | size_type | | stl.h:176:35:176:44 | operator+= | 0 | const func:0 & |
| stl.h:176:35:176:44 | operator+= | 0 | size_type | | stl.h:176:35:176:44 | operator+= | 0 | const func:0 & |
| stl.h:177:17:177:26 | operator+= | 0 | const func:0 & | | stl.h:177:17:177:26 | operator+= | 0 | const class:0 * |
| stl.h:178:17:178:22 | append | 0 | const class:0 * | | stl.h:178:17:178:22 | append | 0 | const basic_string & |
| stl.h:179:17:179:22 | append | 0 | const basic_string & | | stl.h:179:17:179:22 | append | 0 | const class:0 * |
| stl.h:180:17:180:22 | append | 0 | const class:0 * | | stl.h:180:17:180:22 | append | 0 | size_type |
| stl.h:181:47:181:52 | append | 0 | size_type | | stl.h:180:17:180:22 | append | 1 | class:0 |
| stl.h:181:47:181:52 | append | 1 | class:0 | | stl.h:181:47:181:52 | append | 0 | func:0 |
| stl.h:182:17:182:22 | assign | 0 | func:0 | | stl.h:181:47:181:52 | append | 1 | func:0 |
| stl.h:182:17:182:22 | assign | 1 | func:0 | | stl.h:182:17:182:22 | assign | 0 | const basic_string & |
| stl.h:183:17:183:22 | assign | 0 | const basic_string & | | stl.h:183:17:183:22 | assign | 0 | size_type |
| stl.h:184:47:184:52 | assign | 0 | size_type | | stl.h:183:17:183:22 | assign | 1 | class:0 |
| stl.h:184:47:184:52 | assign | 1 | class:0 | | stl.h:184:47:184:52 | assign | 0 | func:0 |
| stl.h:185:17:185:22 | insert | 0 | func:0 | | stl.h:184:47:184:52 | assign | 1 | func:0 |
| stl.h:185:17:185:22 | insert | 1 | func:0 | | stl.h:185:17:185:22 | insert | 0 | size_type |
| stl.h:185:17:185:22 | insert | 1 | const basic_string & |
| stl.h:186:17:186:22 | insert | 0 | size_type | | stl.h:186:17:186:22 | insert | 0 | size_type |
| stl.h:186:17:186:22 | insert | 1 | const basic_string & | | stl.h:186:17:186:22 | insert | 1 | size_type |
| stl.h:186:17:186:22 | insert | 2 | class:0 |
| stl.h:187:17:187:22 | insert | 0 | size_type | | stl.h:187:17:187:22 | insert | 0 | size_type |
| stl.h:187:17:187:22 | insert | 1 | size_type | | stl.h:187:17:187:22 | insert | 1 | const class:0 * |
| stl.h:187:17:187:22 | insert | 2 | class:0 | | stl.h:188:12:188:17 | insert | 0 | const_iterator |
| stl.h:188:12:188:17 | insert | 0 | size_type | | stl.h:188:12:188:17 | insert | 1 | size_type |
| stl.h:188:12:188:17 | insert | 1 | const class:0 * | | stl.h:188:12:188:17 | insert | 2 | class:0 |
| stl.h:189:42:189:47 | insert | 0 | const_iterator | | stl.h:189:42:189:47 | insert | 0 | const_iterator |
| stl.h:189:42:189:47 | insert | 1 | size_type | | stl.h:189:42:189:47 | insert | 1 | func:0 |
| stl.h:189:42:189:47 | insert | 2 | class:0 | | stl.h:189:42:189:47 | insert | 2 | func:0 |
| stl.h:190:17:190:23 | replace | 0 | const_iterator | | stl.h:190:17:190:23 | replace | 0 | size_type |
| stl.h:190:17:190:23 | replace | 1 | func:0 | | stl.h:190:17:190:23 | replace | 1 | size_type |
| stl.h:190:17:190:23 | replace | 2 | func:0 | | stl.h:190:17:190:23 | replace | 2 | const basic_string & |
| stl.h:191:17:191:23 | replace | 0 | size_type | | stl.h:191:17:191:23 | replace | 0 | size_type |
| stl.h:191:17:191:23 | replace | 1 | size_type | | stl.h:191:17:191:23 | replace | 1 | size_type |
| stl.h:191:17:191:23 | replace | 2 | const basic_string & | | stl.h:191:17:191:23 | replace | 2 | size_type |
| stl.h:192:13:192:16 | copy | 0 | size_type | | stl.h:191:17:191:23 | replace | 3 | class:0 |
| stl.h:192:13:192:16 | copy | 0 | class:0 * |
| stl.h:192:13:192:16 | copy | 1 | size_type | | stl.h:192:13:192:16 | copy | 1 | size_type |
| stl.h:192:13:192:16 | copy | 2 | size_type | | stl.h:192:13:192:16 | copy | 2 | size_type |
| stl.h:192:13:192:16 | copy | 3 | class:0 | | stl.h:194:16:194:21 | substr | 0 | size_type |
| stl.h:193:8:193:12 | clear | 0 | class:0 * | | stl.h:194:16:194:21 | substr | 1 | size_type |
| stl.h:193:8:193:12 | clear | 1 | size_type | | stl.h:195:8:195:11 | swap | 0 | basic_string & |
| stl.h:193:8:193:12 | clear | 2 | size_type |
| stl.h:195:8:195:11 | swap | 0 | size_type |
| stl.h:195:8:195:11 | swap | 1 | size_type |
| stl.h:198:94:198:102 | operator+ | 0 | const basic_string & | | stl.h:198:94:198:102 | operator+ | 0 | const basic_string & |
| stl.h:198:94:198:102 | operator+ | 1 | const basic_string & | | stl.h:198:94:198:102 | operator+ | 1 | const basic_string & |
| stl.h:199:94:199:102 | operator+ | 0 | const basic_string & | | stl.h:199:94:199:102 | operator+ | 0 | const basic_string & |

View File

@@ -1,14 +1,14 @@
| file://:0:0:0:0 | E<C>'s friend | loop.cpp:5:26:5:26 | E<D> |
| file://:0:0:0:0 | E<C>'s friend | loop.cpp:5:26:5:26 | E<T> | | file://:0:0:0:0 | E<C>'s friend | loop.cpp:5:26:5:26 | E<T> |
| file://:0:0:0:0 | E<C>'s friend | loop.cpp:10:26:10:26 | F<D> | | file://:0:0:0:0 | E<C>'s friend | loop.cpp:5:26:5:29 | E<D> |
| file://:0:0:0:0 | E<C>'s friend | loop.cpp:10:26:10:26 | F<T> | | file://:0:0:0:0 | E<C>'s friend | loop.cpp:10:26:10:26 | F<T> |
| file://:0:0:0:0 | E<D>'s friend | loop.cpp:5:26:5:26 | E<C> | | file://:0:0:0:0 | E<C>'s friend | loop.cpp:10:26:10:29 | F<D> |
| file://:0:0:0:0 | E<D>'s friend | loop.cpp:5:26:5:26 | E<T> | | file://:0:0:0:0 | E<D>'s friend | loop.cpp:5:26:5:26 | E<T> |
| file://:0:0:0:0 | E<D>'s friend | loop.cpp:10:26:10:26 | F<D> | | file://:0:0:0:0 | E<D>'s friend | loop.cpp:5:26:5:29 | E<C> |
| file://:0:0:0:0 | E<D>'s friend | loop.cpp:10:26:10:26 | F<T> | | file://:0:0:0:0 | E<D>'s friend | loop.cpp:10:26:10:26 | F<T> |
| file://:0:0:0:0 | F<D>'s friend | loop.cpp:5:26:5:26 | E<C> | | file://:0:0:0:0 | E<D>'s friend | loop.cpp:10:26:10:29 | F<D> |
| file://:0:0:0:0 | F<D>'s friend | loop.cpp:5:26:5:26 | E<D> |
| file://:0:0:0:0 | F<D>'s friend | loop.cpp:5:26:5:26 | E<T> | | file://:0:0:0:0 | F<D>'s friend | loop.cpp:5:26:5:26 | E<T> |
| file://:0:0:0:0 | F<D>'s friend | loop.cpp:5:26:5:29 | E<C> |
| file://:0:0:0:0 | F<D>'s friend | loop.cpp:5:26:5:29 | E<D> |
| loop.cpp:6:5:6:5 | E<T>'s friend | loop.cpp:5:26:5:26 | E<T> | | loop.cpp:6:5:6:5 | E<T>'s friend | loop.cpp:5:26:5:26 | E<T> |
| loop.cpp:7:5:7:5 | E<T>'s friend | loop.cpp:7:36:7:36 | F<U> | | loop.cpp:7:5:7:5 | E<T>'s friend | loop.cpp:7:36:7:36 | F<U> |
| loop.cpp:11:5:11:5 | F<T>'s friend | loop.cpp:11:36:11:36 | E<U> | | loop.cpp:11:5:11:5 | F<T>'s friend | loop.cpp:11:36:11:36 | E<U> |

View File

@@ -664,7 +664,7 @@ namespace Semmle.Extraction.CSharp
// Find the (possibly unbound) original extension method that maps to this implementation (if any). // Find the (possibly unbound) original extension method that maps to this implementation (if any).
var unboundDeclaration = extensions.SelectMany(e => e.GetMembers()) var unboundDeclaration = extensions.SelectMany(e => e.GetMembers())
.OfType<IMethodSymbol>() .OfType<IMethodSymbol>()
.FirstOrDefault(m => SymbolEqualityComparer.Default.Equals(m.AssociatedExtensionImplementation, method.ConstructedFrom)); .FirstOrDefault(m => SymbolEqualityComparer.Default.Equals(m.AssociatedExtensionImplementation?.ConstructedFrom, method.ConstructedFrom));
var isFullyConstructed = method.IsBoundGenericMethod(); var isFullyConstructed = method.IsBoundGenericMethod();
if (isFullyConstructed && unboundDeclaration?.ContainingType is INamedTypeSymbol extensionType) if (isFullyConstructed && unboundDeclaration?.ContainingType is INamedTypeSymbol extensionType)

View File

@@ -69,6 +69,7 @@ namespace Semmle.Extraction.CSharp.Entities
} }
Overrides(trapFile); Overrides(trapFile);
ExtractRefReturn(trapFile, Symbol, this);
if (Symbol.FromSource() && !HasBody) if (Symbol.FromSource() && !HasBody)
{ {

View File

@@ -4,7 +4,7 @@ source https://api.nuget.org/v3/index.json
# behave like nuget in choosing transitive dependency versions # behave like nuget in choosing transitive dependency versions
strategy: max strategy: max
nuget Basic.CompilerLog.Util 0.9.25 nuget Basic.CompilerLog.Util 0.9.39
nuget Mono.Posix.NETStandard nuget Mono.Posix.NETStandard
nuget Newtonsoft.Json nuget Newtonsoft.Json
nuget NuGet.Versioning nuget NuGet.Versioning
@@ -12,7 +12,7 @@ nuget xunit
nuget xunit.runner.visualstudio nuget xunit.runner.visualstudio
nuget xunit.runner.utility nuget xunit.runner.utility
nuget Microsoft.NET.Test.Sdk nuget Microsoft.NET.Test.Sdk
nuget Microsoft.CodeAnalysis.CSharp 5.0.0 nuget Microsoft.CodeAnalysis.CSharp 5.3.0
nuget Microsoft.CodeAnalysis 5.0.0 nuget Microsoft.CodeAnalysis 5.3.0
nuget Microsoft.Build 18.0.2 nuget Microsoft.Build 18.6.3
nuget Microsoft.VisualStudio.SolutionPersistence nuget Microsoft.VisualStudio.SolutionPersistence

100
csharp/paket.lock generated
View File

@@ -3,45 +3,42 @@ STRATEGY: MAX
RESTRICTION: == net10.0 RESTRICTION: == net10.0
NUGET NUGET
remote: https://api.nuget.org/v3/index.json remote: https://api.nuget.org/v3/index.json
Basic.CompilerLog.Util (0.9.25) Basic.CompilerLog.Util (0.9.39)
MessagePack (>= 3.1.4) MessagePack (>= 3.1.4)
Microsoft.Bcl.Memory (>= 9.0.10) Microsoft.Bcl.Memory (>= 10.0.7)
Microsoft.CodeAnalysis (>= 4.8) Microsoft.CodeAnalysis (>= 4.8)
Microsoft.CodeAnalysis.CSharp (>= 4.8) Microsoft.CodeAnalysis.CSharp (>= 4.8)
Microsoft.CodeAnalysis.VisualBasic (>= 4.8) Microsoft.CodeAnalysis.VisualBasic (>= 4.8)
Microsoft.Extensions.ObjectPool (>= 9.0.10) Microsoft.Extensions.ObjectPool (>= 10.0.7)
MSBuild.StructuredLogger (>= 2.3.71) MSBuild.StructuredLogger (>= 2.3.178)
NaturalSort.Extension (>= 4.4)
NuGet.Versioning (>= 6.14)
Humanizer.Core (3.0.10) Humanizer.Core (3.0.10)
MessagePack (3.1.4) MessagePack (3.1.6)
MessagePack.Annotations (>= 3.1.4) MessagePack.Annotations (>= 3.1.6)
MessagePackAnalyzer (>= 3.1.4) MessagePackAnalyzer (>= 3.1.6)
Microsoft.NET.StringTools (>= 17.11.4) Microsoft.NET.StringTools (>= 17.11.4)
MessagePack.Annotations (3.1.4) MessagePack.Annotations (3.1.6)
MessagePackAnalyzer (3.1.4) MessagePackAnalyzer (3.1.6)
Microsoft.Bcl.AsyncInterfaces (10.0.8) Microsoft.Bcl.AsyncInterfaces (10.0.8)
Microsoft.Bcl.Memory (10.0.8) Microsoft.Bcl.Memory (10.0.8)
Microsoft.Build (18.0.2) Microsoft.Build (18.6.3)
Microsoft.Build.Framework (>= 18.0.2) Microsoft.Build.Framework (>= 18.6.3)
Microsoft.NET.StringTools (>= 18.0.2) System.Configuration.ConfigurationManager (>= 10.0.3)
System.Configuration.ConfigurationManager (>= 9.0) System.Diagnostics.EventLog (>= 10.0.3)
System.Diagnostics.EventLog (>= 9.0) System.Reflection.MetadataLoadContext (>= 10.0.3)
System.Reflection.MetadataLoadContext (>= 9.0) System.Security.Cryptography.ProtectedData (>= 10.0.3)
System.Security.Cryptography.ProtectedData (>= 9.0.6) Microsoft.Build.Framework (18.6.3)
Microsoft.Build.Framework (18.4) Microsoft.NET.StringTools (>= 18.6.3)
Microsoft.Build.Utilities.Core (18.4) Microsoft.Build.Utilities.Core (18.6.3)
Microsoft.Build.Framework (>= 18.4) Microsoft.Build.Framework (>= 18.6.3)
Microsoft.NET.StringTools (>= 18.4) System.Configuration.ConfigurationManager (>= 10.0.3)
System.Configuration.ConfigurationManager (>= 10.0.1) System.Diagnostics.EventLog (>= 10.0.3)
System.Diagnostics.EventLog (>= 10.0.1) System.Security.Cryptography.ProtectedData (>= 10.0.3)
System.Security.Cryptography.ProtectedData (>= 10.0.1) Microsoft.CodeAnalysis (5.3)
Microsoft.CodeAnalysis (5.0)
Humanizer.Core (>= 2.14.1) Humanizer.Core (>= 2.14.1)
Microsoft.Bcl.AsyncInterfaces (>= 9.0) Microsoft.Bcl.AsyncInterfaces (>= 9.0)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.CSharp.Workspaces (5.0) Microsoft.CodeAnalysis.CSharp.Workspaces (5.3)
Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.0) Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.3)
System.Buffers (>= 4.6) System.Buffers (>= 4.6)
System.Collections.Immutable (>= 9.0) System.Collections.Immutable (>= 9.0)
System.Composition (>= 9.0) System.Composition (>= 9.0)
@@ -54,36 +51,36 @@ NUGET
System.Threading.Channels (>= 8.0) System.Threading.Channels (>= 8.0)
System.Threading.Tasks.Extensions (>= 4.6) System.Threading.Tasks.Extensions (>= 4.6)
Microsoft.CodeAnalysis.Analyzers (5.3) Microsoft.CodeAnalysis.Analyzers (5.3)
Microsoft.CodeAnalysis.Common (5.0) Microsoft.CodeAnalysis.Common (5.3)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.CSharp (5.0) Microsoft.CodeAnalysis.CSharp (5.3)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.Common (5.0) Microsoft.CodeAnalysis.Common (5.3)
Microsoft.CodeAnalysis.CSharp.Workspaces (5.0) Microsoft.CodeAnalysis.CSharp.Workspaces (5.3)
Humanizer.Core (>= 2.14.1) Humanizer.Core (>= 2.14.1)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.Common (5.0) Microsoft.CodeAnalysis.Common (5.3)
Microsoft.CodeAnalysis.CSharp (5.0) Microsoft.CodeAnalysis.CSharp (5.3)
Microsoft.CodeAnalysis.Workspaces.Common (5.0) Microsoft.CodeAnalysis.Workspaces.Common (5.3)
System.Composition (>= 9.0) System.Composition (>= 9.0)
Microsoft.CodeAnalysis.VisualBasic (5.0) Microsoft.CodeAnalysis.VisualBasic (5.3)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.Common (5.0) Microsoft.CodeAnalysis.Common (5.3)
Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.0) Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.3)
Humanizer.Core (>= 2.14.1) Humanizer.Core (>= 2.14.1)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.Common (5.0) Microsoft.CodeAnalysis.Common (5.3)
Microsoft.CodeAnalysis.VisualBasic (5.0) Microsoft.CodeAnalysis.VisualBasic (5.3)
Microsoft.CodeAnalysis.Workspaces.Common (5.0) Microsoft.CodeAnalysis.Workspaces.Common (5.3)
System.Composition (>= 9.0) System.Composition (>= 9.0)
Microsoft.CodeAnalysis.Workspaces.Common (5.0) Microsoft.CodeAnalysis.Workspaces.Common (5.3)
Humanizer.Core (>= 2.14.1) Humanizer.Core (>= 2.14.1)
Microsoft.CodeAnalysis.Analyzers (>= 3.11) Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
Microsoft.CodeAnalysis.Common (5.0) Microsoft.CodeAnalysis.Common (5.3)
System.Composition (>= 9.0) System.Composition (>= 9.0)
Microsoft.CodeCoverage (18.5.1) Microsoft.CodeCoverage (18.5.1)
Microsoft.Extensions.ObjectPool (10.0.8) Microsoft.Extensions.ObjectPool (10.0.8)
Microsoft.NET.StringTools (18.4) Microsoft.NET.StringTools (18.6.3)
Microsoft.NET.Test.Sdk (18.5.1) Microsoft.NET.Test.Sdk (18.5.1)
Microsoft.CodeCoverage (>= 18.5.1) Microsoft.CodeCoverage (>= 18.5.1)
Microsoft.TestPlatform.TestHost (>= 18.5.1) Microsoft.TestPlatform.TestHost (>= 18.5.1)
@@ -97,7 +94,6 @@ NUGET
MSBuild.StructuredLogger (2.3.204) MSBuild.StructuredLogger (2.3.204)
Microsoft.Build.Framework (>= 17.5) Microsoft.Build.Framework (>= 17.5)
Microsoft.Build.Utilities.Core (>= 17.5) Microsoft.Build.Utilities.Core (>= 17.5)
NaturalSort.Extension (4.4.1)
Newtonsoft.Json (13.0.4) Newtonsoft.Json (13.0.4)
NuGet.Versioning (7.6) NuGet.Versioning (7.6)
System.Buffers (4.6.1) System.Buffers (4.6.1)

31
csharp/paket.main.bzl generated

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all name: codeql/csharp-solorigate-all
version: 1.7.68 version: 1.7.69-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries name: codeql/csharp-solorigate-queries
version: 1.7.68 version: 1.7.69-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -22,7 +22,6 @@
| [...]/csharp/tools/[...]/Microsoft.Win32.Primitives.dll | | [...]/csharp/tools/[...]/Microsoft.Win32.Primitives.dll |
| [...]/csharp/tools/[...]/Microsoft.Win32.Registry.dll | | [...]/csharp/tools/[...]/Microsoft.Win32.Registry.dll |
| [...]/csharp/tools/[...]/Mono.Posix.NETStandard.dll | | [...]/csharp/tools/[...]/Mono.Posix.NETStandard.dll |
| [...]/csharp/tools/[...]/NaturalSort.Extension.dll |
| [...]/csharp/tools/[...]/Newtonsoft.Json.dll | | [...]/csharp/tools/[...]/Newtonsoft.Json.dll |
| [...]/csharp/tools/[...]/NuGet.Versioning.dll | | [...]/csharp/tools/[...]/NuGet.Versioning.dll |
| [...]/csharp/tools/[...]/StructuredLogger.dll | | [...]/csharp/tools/[...]/StructuredLogger.dll |

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved call target resolution for ref-return properties and indexers.

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all name: codeql/csharp-all
version: 6.0.2 version: 6.0.3-dev
groups: csharp groups: csharp
dbscheme: semmlecode.csharp.dbscheme dbscheme: semmlecode.csharp.dbscheme
extractor: csharp extractor: csharp

View File

@@ -766,7 +766,16 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr {
} }
override Accessor getWriteTarget() { override Accessor getWriteTarget() {
this instanceof AssignableWrite and result = this.getProperty().getSetter() this instanceof AssignableWrite and
exists(Property p | p = this.getProperty() |
result = p.getSetter()
or
result =
any(Getter g |
g = p.getGetter() and
g.getAnnotatedReturnType().isRef()
)
)
} }
override Expr getArgument(int i) { override Expr getArgument(int i) {
@@ -801,7 +810,16 @@ class IndexerCall extends AccessorCall, IndexerAccessExpr {
} }
override Accessor getWriteTarget() { override Accessor getWriteTarget() {
this instanceof AssignableWrite and result = this.getIndexer().getSetter() this instanceof AssignableWrite and
exists(Indexer i | i = this.getIndexer() |
result = i.getSetter()
or
result =
any(Getter g |
g = i.getGetter() and
g.getAnnotatedReturnType().isRef()
)
)
} }
override Expr getArgument(int i) { override Expr getArgument(int i) {

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries name: codeql/csharp-queries
version: 1.7.4 version: 1.7.5-dev
groups: groups:
- csharp - csharp
- queries - queries

View File

@@ -227,7 +227,7 @@ returnTypes
| NullableRefTypes.cs:107:26:107:36 | ReturnsRef5 | readonly MyClass! | | NullableRefTypes.cs:107:26:107:36 | ReturnsRef5 | readonly MyClass! |
| NullableRefTypes.cs:108:26:108:36 | ReturnsRef6 | readonly MyClass! | | NullableRefTypes.cs:108:26:108:36 | ReturnsRef6 | readonly MyClass! |
| NullableRefTypes.cs:110:10:110:20 | Parameters1 | Void! | | NullableRefTypes.cs:110:10:110:20 | Parameters1 | Void! |
| NullableRefTypes.cs:113:32:113:44 | get_RefProperty | MyClass! | | NullableRefTypes.cs:113:32:113:44 | get_RefProperty | ref MyClass! |
| NullableRefTypes.cs:116:7:116:23 | <object initializer> | Void | | NullableRefTypes.cs:116:7:116:23 | <object initializer> | Void |
| NullableRefTypes.cs:116:7:116:23 | ToStringWithTypes | Void! | | NullableRefTypes.cs:116:7:116:23 | ToStringWithTypes | Void! |
| NullableRefTypes.cs:136:7:136:24 | <object initializer> | Void | | NullableRefTypes.cs:136:7:136:24 | <object initializer> | Void |

View File

@@ -1,4 +1,4 @@
class SBCS class SBCS
{ {
string sbcs = "<22>"; string sbcs = "<22>";
} }

View File

@@ -0,0 +1,4 @@
| indexers.cs:24:21:24:24 | Item | indexers.cs:62:22:62:29 | access to indexer | indexers.cs:26:13:26:15 | get_Item |
| indexers.cs:24:21:24:24 | Item | indexers.cs:65:25:65:32 | access to indexer | indexers.cs:34:13:34:15 | set_Item |
| indexers.cs:143:24:143:27 | Item | indexers.cs:156:13:156:16 | access to indexer | indexers.cs:145:13:145:15 | get_Item |
| indexers.cs:143:24:143:27 | Item | indexers.cs:157:21:157:24 | access to indexer | indexers.cs:145:13:145:15 | get_Item |

View File

@@ -0,0 +1,8 @@
import csharp
from IndexerCall ic, Indexer i, Accessor target
where
ic.getIndexer() = i and
ic.getTarget() = target and
i.fromSource()
select i, ic, target

View File

@@ -360,3 +360,57 @@ indexers.cs:
# 130| 4: [BlockStmt] {...} # 130| 4: [BlockStmt] {...}
# 130| 0: [ReturnStmt] return ...; # 130| 0: [ReturnStmt] return ...;
# 130| 0: [IntLiteral] 0 # 130| 0: [IntLiteral] 0
# 134| 5: [RefStruct] S
# 136| 6: [Field] x
# 136| -1: [TypeMention] int
# 138| 7: [InstanceConstructor] S
#-----| 2: (Parameters)
# 138| 0: [Parameter] v
# 138| -1: [TypeMention] int
# 139| 4: [BlockStmt] {...}
# 140| 0: [ExprStmt] ...;
# 140| 0: [AssignExpr] ... = ...
# 140| 0: [FieldAccess] access to field x
# 140| 1: [RefExpr] ref ...
# 140| 0: [ParameterAccess] access to parameter v
# 143| 8: [Indexer] Item
# 143| -1: [TypeMention] int
#-----| 1: (Parameters)
# 143| 0: [Parameter] i
# 143| -1: [TypeMention] int
# 145| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 143| 0: [Parameter] i
# 145| 4: [BlockStmt] {...}
# 145| 0: [ReturnStmt] return ...;
# 145| 0: [RefExpr] ref ...
# 145| 0: [FieldAccess] access to field x
# 149| 6: [Class] TestRefReturns
# 151| 6: [Method] M
# 151| -1: [TypeMention] Void
# 152| 4: [BlockStmt] {...}
# 153| 0: [LocalVariableDeclStmt] ... ...;
# 153| 0: [LocalVariableDeclAndInitExpr] Int32 a = ...
# 153| -1: [TypeMention] int
# 153| 0: [LocalVariableAccess] access to local variable a
# 153| 1: [IntLiteral] 0
# 155| 1: [LocalVariableDeclStmt] ... ...;
# 155| 0: [LocalVariableDeclAndInitExpr] S s = ...
# 155| -1: [TypeMention] S
# 155| 0: [LocalVariableAccess] access to local variable s
# 155| 1: [ObjectCreation] object creation of type S
# 155| -1: [TypeMention] S
# 155| 0: [LocalVariableAccess] access to local variable a
# 156| 2: [ExprStmt] ...;
# 156| 0: [AssignExpr] ... = ...
# 156| 0: [IndexerCall] access to indexer
# 156| -1: [LocalVariableAccess] access to local variable s
# 156| 0: [IntLiteral] 0
# 156| 1: [IntLiteral] 1
# 157| 3: [LocalVariableDeclStmt] ... ...;
# 157| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 157| -1: [TypeMention] int
# 157| 0: [LocalVariableAccess] access to local variable x
# 157| 1: [IndexerCall] access to indexer
# 157| -1: [LocalVariableAccess] access to local variable s
# 157| 0: [IntLiteral] 0

View File

@@ -130,4 +130,31 @@ namespace Indexers
get { return 0; } get { return 0; }
} }
} }
public ref struct S
{
private ref int x;
public S(ref int v)
{
x = ref v;
}
public ref int this[int i]
{
get { return ref x; }
}
}
public class TestRefReturns
{
public void M()
{
int a = 0;
S s = new S(ref a);
s[0] = 1;
var x = s[0];
}
}
} }

View File

@@ -246,3 +246,50 @@ properties.cs:
# 133| 0: [FieldAccess] access to field Prop.field # 133| 0: [FieldAccess] access to field Prop.field
# 133| 1: [ParameterAccess] access to parameter value # 133| 1: [ParameterAccess] access to parameter value
# 130| 7: [Field] Prop.field # 130| 7: [Field] Prop.field
# 137| 11: [RefStruct] S
# 139| 6: [Field] x
# 139| -1: [TypeMention] int
# 141| 7: [InstanceConstructor] S
#-----| 2: (Parameters)
# 141| 0: [Parameter] v
# 141| -1: [TypeMention] int
# 142| 4: [BlockStmt] {...}
# 143| 0: [ExprStmt] ...;
# 143| 0: [AssignExpr] ... = ...
# 143| 0: [FieldAccess] access to field x
# 143| 1: [RefExpr] ref ...
# 143| 0: [ParameterAccess] access to parameter v
# 146| 8: [Property] Prop
# 146| -1: [TypeMention] int
# 148| 3: [Getter] get_Prop
# 148| 4: [BlockStmt] {...}
# 148| 0: [ReturnStmt] return ...;
# 148| 0: [RefExpr] ref ...
# 148| 0: [FieldAccess] access to field x
# 152| 12: [Class] TestRefReturns
# 154| 6: [Method] M
# 154| -1: [TypeMention] Void
# 155| 4: [BlockStmt] {...}
# 156| 0: [LocalVariableDeclStmt] ... ...;
# 156| 0: [LocalVariableDeclAndInitExpr] Int32 a = ...
# 156| -1: [TypeMention] int
# 156| 0: [LocalVariableAccess] access to local variable a
# 156| 1: [IntLiteral] 0
# 158| 1: [LocalVariableDeclStmt] ... ...;
# 158| 0: [LocalVariableDeclAndInitExpr] S s = ...
# 158| -1: [TypeMention] S
# 158| 0: [LocalVariableAccess] access to local variable s
# 158| 1: [ObjectCreation] object creation of type S
# 158| -1: [TypeMention] S
# 158| 0: [LocalVariableAccess] access to local variable a
# 159| 2: [ExprStmt] ...;
# 159| 0: [AssignExpr] ... = ...
# 159| 0: [PropertyCall] access to property Prop
# 159| -1: [LocalVariableAccess] access to local variable s
# 159| 1: [IntLiteral] 1
# 160| 3: [LocalVariableDeclStmt] ... ...;
# 160| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 160| -1: [TypeMention] int
# 160| 0: [LocalVariableAccess] access to local variable x
# 160| 1: [PropertyCall] access to property Prop
# 160| -1: [LocalVariableAccess] access to local variable s

View File

@@ -1,5 +1,6 @@
| Prop.field | | Prop.field |
| caption | | caption |
| next | | next |
| x |
| y | | y |
| z | | z |

View File

@@ -0,0 +1,8 @@
| properties.cs:12:23:12:29 | Caption | properties.cs:29:13:29:28 | access to property Caption | properties.cs:17:13:17:15 | set_Caption |
| properties.cs:12:23:12:29 | Caption | properties.cs:30:24:30:39 | access to property Caption | properties.cs:15:13:15:15 | get_Caption |
| properties.cs:57:20:57:20 | X | properties.cs:61:13:61:13 | access to property X | properties.cs:57:37:57:39 | set_X |
| properties.cs:58:20:58:20 | Y | properties.cs:62:13:62:13 | access to property Y | properties.cs:58:37:58:39 | set_Y |
| properties.cs:70:28:70:28 | X | properties.cs:82:46:82:51 | access to property X | properties.cs:70:32:70:34 | get_X |
| properties.cs:71:28:71:28 | Y | properties.cs:83:39:83:44 | access to property Y | properties.cs:74:13:74:15 | set_Y |
| properties.cs:146:24:146:27 | Prop | properties.cs:159:13:159:18 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
| properties.cs:146:24:146:27 | Prop | properties.cs:160:21:160:26 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |

View File

@@ -0,0 +1,8 @@
import csharp
from PropertyCall pc, Property p, Accessor target
where
pc.getProperty() = p and
pc.getTarget() = target and
p.fromSource()
select p, pc, target

View File

@@ -133,4 +133,31 @@ namespace Properties
set { field = value; } set { field = value; }
} }
} }
public ref struct S
{
private ref int x;
public S(ref int v)
{
x = ref v;
}
public ref int Prop
{
get { return ref x; }
}
}
public class TestRefReturns
{
public void M()
{
int a = 0;
S s = new S(ref a);
s.Prop = 1;
var x = s.Prop;
}
}
} }

View File

@@ -1,3 +1,2 @@
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer | | Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer | | Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
| Quality.cs:32:9:32:21 | access to indexer | Call without target $@. | Quality.cs:32:9:32:21 | access to indexer | access to indexer |

View File

@@ -9,6 +9,5 @@
| Quality.cs:23:9:23:30 | delegate call | Call without target $@. | Quality.cs:23:9:23:30 | delegate call | delegate call | | Quality.cs:23:9:23:30 | delegate call | Call without target $@. | Quality.cs:23:9:23:30 | delegate call | delegate call |
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer | | Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer | | Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
| Quality.cs:32:9:32:21 | access to indexer | Call without target $@. | Quality.cs:32:9:32:21 | access to indexer | access to indexer |
| Quality.cs:38:16:38:26 | access to property MyProperty2 | Call without target $@. | Quality.cs:38:16:38:26 | access to property MyProperty2 | access to property MyProperty2 | | Quality.cs:38:16:38:26 | access to property MyProperty2 | Call without target $@. | Quality.cs:38:16:38:26 | access to property MyProperty2 | access to property MyProperty2 |
| Quality.cs:50:20:50:26 | object creation of type T | Call without target $@. | Quality.cs:50:20:50:26 | object creation of type T | object creation of type T | | Quality.cs:50:20:50:26 | object creation of type T | Call without target $@. | Quality.cs:50:20:50:26 | object creation of type T | object creation of type T |

View File

@@ -29,7 +29,7 @@ public class Test
var slice = sp[..3]; // TODO: this is not an indexer call, but rather a `sp.Slice(0, 3)` call. var slice = sp[..3]; // TODO: this is not an indexer call, but rather a `sp.Slice(0, 3)` call.
Span<byte> guidBytes = stackalloc byte[16]; Span<byte> guidBytes = stackalloc byte[16];
guidBytes[08] = 1; // TODO: this indexer call has no target, because the target is a `ref` returning getter. guidBytes[08] = 1;
new MyList([new(), new Test()]); new MyList([new(), new Test()]);
} }

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

@@ -1,5 +1,5 @@
name: codeql-go-consistency-queries name: codeql-go-consistency-queries
version: 1.0.51 version: 1.0.52-dev
groups: groups:
- go - go
- queries - queries

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/go-all name: codeql/go-all
version: 7.1.2 version: 7.1.3-dev
groups: go groups: go
dbscheme: go.dbscheme dbscheme: go.dbscheme
extractor: go extractor: go

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,5 +1,5 @@
name: codeql/go-queries name: codeql/go-queries
version: 1.6.4 version: 1.6.5-dev
groups: groups:
- go - go
- queries - queries

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

@@ -64,8 +64,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 != "src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar"
] ]
_compiler_plugin_registrar_service = (
"src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar",
"META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar",
)
kt_javac_options( kt_javac_options(
name = "javac-options", name = "javac-options",
release = "8", release = "8",
@@ -91,19 +97,26 @@ 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>()
@@ -7808,7 +7808,7 @@ open class KotlinFileExtractor(
* constructor(dispatchReceiver: TD, extensionReceiver: TE) { * constructor(dispatchReceiver: TD, extensionReceiver: TE) {
* super() * super()
* this.dispatchReceiver = dispatchReceiver * this.dispatchReceiver = dispatchReceiver
* this.extensionReceiver = extensionReceiver * this.codeQlExtensionReceiver = extensionReceiver
* } * }
* fun invoke(a0:T0, a1:T1, ... aI: TI): R { return this.dispatchReceiver.FN(a0,a1,...,aI) } OR * fun invoke(a0:T0, a1:T1, ... aI: TI): R { return this.dispatchReceiver.FN(a0,a1,...,aI) } OR
* fun invoke( a1:T1, ... aI: TI): R { return this.dispatchReceiver.FN(this.dispatchReceiver,a1,...,aI) } OR * fun invoke( a1:T1, ... aI: TI): R { return this.dispatchReceiver.FN(this.dispatchReceiver,a1,...,aI) } OR
@@ -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,71 @@
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
var IrMemberAccessExpression<*>.codeQlExtensionReceiver: IrExpression?
get() = extensionReceiver
set(value) { extensionReceiver = value }
// 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)
}
} }

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