Compare commits

..

172 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
f3c85c0ff7 Extend C# control flow elements with type mentions 2026-06-22 13:17:44 +00:00
copilot-swe-agent[bot]
d7ec468e2e Add type mentions to control flow element handling 2026-06-22 12:29:48 +00:00
Anders Schack-Mulligen
7197cc56dd Merge pull request #22014 from github/copilot/update-rescue-clause-exception-handling
Ruby AST: preserve ExceptionList node in RescueClause for 2+ exceptions
2026-06-22 13:28:29 +02:00
Anders Schack-Mulligen
48b0cbcf01 Merge pull request #22031 from github/copilot/tweak-csharp-extractor
Extract `TypeMention` for `catch (Exception)` clauses
2026-06-22 13:27:47 +02:00
Anders Schack-Mulligen
ac7ed0612d C#: Accept test change. 2026-06-22 13:00:55 +02:00
Jeroen Ketema
03187ae8be Merge pull request #22013 from jketema/swift/more-arguments
Swift: Strip out more unknown clang arguments
2026-06-22 12:35:36 +02:00
copilot-swe-agent[bot]
bd84fb31e1 Add regression for catch type mention extraction 2026-06-22 09:41:55 +00:00
copilot-swe-agent[bot]
4c9fa4dddc Emit catch type mentions without variables 2026-06-22 09:37:24 +00:00
Anders Schack-Mulligen
7d66ec0f39 Ruby: Clarify AST. 2026-06-22 11:14:53 +02:00
Idriss Riouak
568a147f77 Merge pull request #22007 from github/java-update-ferstl-depgraph-cves
Java: update ferstl depgraph cves
2026-06-22 10:08:05 +02:00
Sotiris Dragonas
d86ec1a4b4 Merge pull request #22012 from github/bazookamusic/js-prompt-injection-sinks
JS Prompt Injection - Add some more sinks and reclassify legacy API
2026-06-19 17:41:41 +03:00
Owen Mansel-Chan
b54d95d7c8 Merge pull request #21967 from github/copilot/conversion-of-codeql-queries
Convert selected Python qlref tests to inline expectations
2026-06-19 14:56:36 +01:00
Michael Nebel
a076ffcc9a Merge pull request #21996 from michaelnebel/csharp/fixpathcombineissues
C#: Fix the `cs/path-combine` code quality issues in the extractor.
2026-06-19 15:49:24 +02:00
Owen Mansel-Chan
f65d1e82cf Merge pull request #21554 from github/copilot/make-go-use-ssa-library
Go: use shared SSA library (codeql.ssa.Ssa)
2026-06-19 13:40:37 +01:00
Owen Mansel-Chan
27f6ffc00e Delete accidentally included text file 2026-06-19 13:24:06 +01:00
Owen Mansel-Chan
c9d45217d2 Fix order of comments in test 2026-06-19 13:23:52 +01:00
Jeroen Ketema
75328daf71 Swift: Match quotes 2026-06-19 13:55:19 +02:00
Anders Schack-Mulligen
6fbb572950 Ruby: Get rid of the change note. 2026-06-19 13:27:34 +02:00
Anders Schack-Mulligen
132b476acd Ruby: autoformat 2026-06-19 13:26:10 +02:00
copilot-swe-agent[bot]
65b4a4346b Add ExceptionList AST node for rescue clauses with 2+ exceptions 2026-06-19 13:26:06 +02:00
Owen Mansel-Chan
451fc2e4e7 Undo conversion for queries that import LegacyPointsTo 2026-06-19 12:22:42 +01:00
Owen Mansel-Chan
5497f2c5fe Convert Python qlref tests to inline expectations 2026-06-19 12:22:40 +01:00
Anders Schack-Mulligen
0834e640bb Ruby: Prepare qltest change by line renumbering. 2026-06-19 13:15:18 +02:00
Owen Mansel-Chan
1496fb6b12 Shared: allow comment starting with # after inline expectation comment 2026-06-19 11:20:30 +01:00
Sotiris Dragonas
38435fc3f2 Merge branch 'main' into bazookamusic/js-prompt-injection-sinks 2026-06-19 12:19:50 +03:00
Jeroen Ketema
b743ad9a49 Swift: Strip out more unknown clang arguments 2026-06-19 11:08:55 +02:00
Michael Nebel
03b525b689 C#: Handle the places where we could risk that Path.Combine would have thrown away the first argument. 2026-06-19 10:22:52 +02:00
Michael Nebel
f7b3f851e8 C#: Rename PathCombine to PathJoin. 2026-06-19 10:22:49 +02:00
Michael Nebel
131d4a0d81 C#: Fix the cs/path-combine code quality issues in the extractor. 2026-06-19 10:22:40 +02:00
Michael Nebel
2686026608 Merge pull request #21993 from michaelnebel/csharp/dropmono
C#: Only use `nuget.exe` on Windows or machines with Mono.
2026-06-19 09:53:04 +02:00
idrissrio
ebb74a56f6 Java: accept new test results 2026-06-19 09:38:16 +02:00
Owen Mansel-Chan
1d69c30ec1 Merge pull request #22010 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-06-19 03:26:14 +01:00
github-actions[bot]
65a3153066 Add changed framework coverage reports 2026-06-19 01:06:45 +00:00
Sotiris Dragonas
ea87f59480 JS: Add and reclassify prompt-injection sinks for AI SDKs
Add missing system/user prompt-injection sinks across the OpenAI,
Anthropic, and Google GenAI JavaScript models:

- OpenAI videos.create/edit/extend/remix prompts (user)
- OpenAI beta.realtime.sessions.create instructions (system)
- Anthropic legacy completions.create prompt (user)
- Google GenAI caches.create config.systemInstruction (system)
- Google GenAI caches.create config.contents (user)

Also reclassify the OpenAI legacy completions.create prompt from
system-prompt-injection to user-prompt-injection: the legacy
/v1/completions endpoint takes a single free-form prompt with no role
separation, so it is the text-in/text-out equivalent of a user message.

Note: videos.remix takes the prompt in Argument[1] (remix(videoID, body)),
and Google GenAI caches.create nests both contents and systemInstruction
under config, so the model entries differ slightly from a naive mapping.

Add corresponding test cases with inline annotations and regenerate the
.expected files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-18 17:32:10 +03:00
Owen Mansel-Chan
db5fac17bf Add QLDoc to MakeSsa to silence CI 2026-06-18 14:54:21 +01:00
Owen Mansel-Chan
fc06aa1a32 Update expected data flow consistency results 2026-06-18 14:54:19 +01:00
idrissrio
99fb3879b2 Java: update ferstl script 2026-06-18 15:43:30 +02:00
Henry Mercer
4e7e363067 Merge branch 'main' into copilot/make-go-use-ssa-library 2026-06-18 14:31:47 +01:00
Anders Schack-Mulligen
779309edb1 Merge pull request #21999 from aschackmull/cfg/parameter-pattern
Cfg: Distinguish parameters from their patterns.
2026-06-18 15:18:22 +02:00
Owen Mansel-Chan
2d34b0be1b Merge branch 'main' into copilot/make-go-use-ssa-library 2026-06-18 14:09:20 +01:00
Owen Mansel-Chan
8c07e95f05 Rename mayCapture to mayUpdateCapturedVariable 2026-06-18 12:41:25 +01:00
Owen Mansel-Chan
f04c8ccbc7 Use module already provided by BasicBlocks lib 2026-06-18 12:37:27 +01:00
Owen Mansel-Chan
7222f1d3ad Remove change note 2026-06-18 12:34:20 +01:00
Jeroen Ketema
5016fcb396 Merge pull request #21995 from jketema/jketema/tele
Java: Update expected test results after extractor changes
2026-06-18 12:51:29 +02:00
Michael Nebel
142a72c77b C#: Address review comments. 2026-06-18 12:48:09 +02:00
Owen Mansel-Chan
330e904449 Merge pull request #22004 from sauyon/go-model-log-slog
Go: Model `log/slog` as a logging sink
2026-06-18 11:20:08 +01:00
Anders Schack-Mulligen
f844cd3754 Java/C#: Adapt to signature change. 2026-06-18 11:00:30 +02:00
Anders Schack-Mulligen
3a3ec1be90 Cfg: Distinguish parameters from their patterns. 2026-06-18 11:00:30 +02:00
Michael Nebel
c747352f41 C#: Fix some code quality issues by replacing Path.Combine with Path.Join. 2026-06-18 08:28:58 +02:00
Michael Nebel
dfdd12190e C#: Rename NugetExeWrapper to PackagesConfigRestorer. 2026-06-18 08:28:56 +02:00
Michael Nebel
63057db753 C#: Only download and use nuget.exe in case of windows or mono is installed. 2026-06-18 08:28:54 +02:00
Michael Nebel
21f8caf153 C#: Re-factor the NugetExeWrapper, introduce an interface and a factory method for constructing package config restorers. 2026-06-18 08:28:51 +02:00
Michael Nebel
9b34cfa362 C#: Invert logic in HasPackageSource. 2026-06-18 08:28:49 +02:00
Michael Nebel
944d76de44 C#: Use the build actions IsWindows in the NugetExeWrapper. 2026-06-18 08:28:47 +02:00
sauyon
b7ef551b52 Address review: exercise variadic args/attrs in slog Log/LogAttrs tests
Copilot review on #22004: the Log/LogAttrs test cases didn't pass any
variadic args/attrs, so the Argument[..3] portion of the sink range was
untested. Pass an ...any arg to slog.Log/Logger.Log and a slog.Attr to
slog.LogAttrs/Logger.LogAttrs, with inline expectations asserting they're
captured as logged components.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 20:27:00 -07:00
sauyon
00427d204c Go: Model log/slog as a logging sink
The standard-library structured logger `log/slog` (Go 1.21+) was not
modeled, so `go/log-injection` and `go/clear-text-logging` were blind to
any code that logs through it.

Model its logging functions and `*slog.Logger` methods — `Debug`, `Info`,
`Warn`, `Error`, their `Context` variants, and `Log`/`LogAttrs` — as
`log-injection` sinks (the kind that feeds `LoggerCall`, powering both
queries). Adds `log/slog` cases to the `LoggerCall` library test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 20:02:29 -07:00
Owen Mansel-Chan
e618883866 Merge pull request #21969 from github/copilot/investigate-missing-alerts
Python: Track instance attributes through type tracking
2026-06-18 00:04:45 +01:00
Owen Mansel-Chan
c7c1eca415 Merge branch 'main' into copilot/investigate-missing-alerts 2026-06-17 22:54:22 +01:00
Mathias Vorreiter Pedersen
3dd3e2c643 Merge pull request #21998 from MathiasVP/fix-autogenerated-dbschemes
Shared/Python: #21935 follow up
2026-06-17 17:30:20 +01:00
Mathias Vorreiter Pedersen
55f2f041ee Shared: Ensure that YAML comment extraction is properly reflected in the dbscheme template. 2026-06-17 17:05:04 +01:00
Mathias Vorreiter Pedersen
004a5b4645 Python: Ensure that YAML comment extraction is properly reflected in the dbscheme template. 2026-06-17 17:04:43 +01:00
Jeroen Ketema
fefe01ecbf Java: Update expected test results after extractor changes 2026-06-17 17:40:23 +02:00
Sotiris Dragonas
7960c5c291 Merge pull request #21953 from github/bazookamusic/cwe-1427
[Javascript] Prompt Injection queries
2026-06-17 18:05:18 +03:00
Sotiris Dragonas
57f20064ba Merge branch 'main' into bazookamusic/cwe-1427 2026-06-17 17:12:20 +03:00
Owen Mansel-Chan
1f9899d7db Extend added type tracking step to related types 2026-06-17 15:04:53 +01:00
Owen Mansel-Chan
dd61dd2d74 Fix FP for py/modification-of-locals 2026-06-17 14:24:18 +01:00
Owen Mansel-Chan
47c2c9e763 Add test for FP for py/modification-of-locals 2026-06-17 14:22:42 +01:00
Michael B. Gale
1cb5be52d0 Merge branch 'add-yaml-comments' 2026-06-17 13:59:08 +01:00
Owen Mansel-Chan
ea7510bf72 Refactor ReExposedInstance logic into one place 2026-06-17 13:10:47 +01:00
Owen Mansel-Chan
415857cacb Fix FP for py/should-use-with 2026-06-17 13:01:36 +01:00
Sotiris Dragonas
ac3e38e7ad Merge branch 'main' into bazookamusic/cwe-1427 2026-06-17 14:55:35 +03:00
Owen Mansel-Chan
d72144646a Add test for FP for py/should-use-with 2026-06-17 12:55:17 +01:00
Sotiris Dragonas
b15a1afa24 Merge branch 'bazookamusic/cwe-1427' of https://github.com/github/codeql into bazookamusic/cwe-1427 2026-06-17 14:55:04 +03:00
Sotiris Dragonas
c444f41a3f 1. Enable inline expectations for tests
2. Add annotations for sources
2. Fix a modelling issue in the openai library - missing coverage for a legacy method when moving to MaDs and a mistake in the assistants.create models
2026-06-17 14:53:48 +03:00
Owen Mansel-Chan
199fd864ad Fix FP for py/file-not-closed 2026-06-17 12:36:04 +01:00
Henry Mercer
929870d828 Merge pull request #21994 from github/henrymercer/mergeback-rc-3-22-into-main
Merge `rc/3.22` into `main`
2026-06-17 12:21:52 +01:00
Owen Mansel-Chan
1154db4f86 Merge pull request #21957 from owen-mc/go/fix-result-node
Go: fix `DataFlow::ResultNode` and some related things
2026-06-17 12:20:27 +01:00
Owen Mansel-Chan
890969433f Add test for FP for py/file-not-closed 2026-06-17 12:19:03 +01:00
Mathias Vorreiter Pedersen
71daa20313 Merge branch 'main' into add-yaml-comments 2026-06-17 12:07:21 +01:00
Owen Mansel-Chan
0a065c93de Update QLDoc for ResultNode 2026-06-17 11:03:23 +01:00
Owen Mansel-Chan
6161922ba4 Merge pull request #21940 from owen-mc/go/unhandled-writable-file-close
Go: Improve precision of `go/unhandled-writable-file-close`
2026-06-17 10:58:08 +01:00
Owen Mansel-Chan
df416fa542 Merge pull request #21977 from owen-mc/code-owners-actions
Make alert coverage team the code owners for `/actions/`
2026-06-17 10:56:52 +01:00
Sotiris Dragonas
274f014d31 Merge branch 'main' into bazookamusic/cwe-1427 2026-06-17 12:53:03 +03:00
Sotiris Dragonas
b9025a54af Fix prompt injection severity 2026-06-17 12:52:33 +03:00
Henry Mercer
1d11151135 Merge rc/3.22 into main 2026-06-17 10:41:44 +01:00
Jeroen Ketema
e6e5f0dffd Merge pull request #21992 from jketema/jketema/swift-filter
Swift: Filter more clang options not recognized by off-the-shelf clang
2026-06-17 11:32:58 +02:00
Mathias Vorreiter Pedersen
c12cf88c52 Merge branch 'main' into add-yaml-comments 2026-06-17 10:17:06 +01:00
Anders Schack-Mulligen
3654205ae2 Merge pull request #21991 from github/copilot/change-ast-for-else-branches
Ruby: Add CaseElseBranch AST node to distinguish else-branch from its body
2026-06-17 09:52:39 +02:00
Anders Schack-Mulligen
027f302932 Ruby: improve return type 2026-06-17 08:47:14 +02:00
Jon Janego
72f34c2b3b Merge pull request #21971 from github/mario-campos/fix-changenote-grammar
Fix changelog copy errors in change-notes and CHANGELOG.md files
2026-06-16 10:15:25 -05:00
Jeroen Ketema
2eb9c54456 Swift: Update test to ensure stabilitry across Xcode versions 2026-06-16 16:57:01 +02:00
Anders Schack-Mulligen
8778e881cb Ruby: Accept two more test changes for new AST node. 2026-06-16 11:14:15 +02:00
Anders Schack-Mulligen
36c1796ef7 Ruby: Fix data flow step. 2026-06-16 11:11:42 +02:00
Sotiris Dragonas
8f965a9614 Grammar
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-16 11:57:58 +03:00
Sotiris Dragonas
d72372c246 Fix system prompt injection description and title
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-16 11:57:37 +03:00
Jeroen Ketema
ef67311af2 Swift: Filter more clang options not recognized by off-the-shelf clang 2026-06-16 10:56:32 +02:00
copilot-swe-agent[bot]
f658bc9b39 Update expected files for CaseElseBranch AST node change 2026-06-15 12:11:22 +00:00
copilot-swe-agent[bot]
8cb4b9b118 Add CaseElseBranch AST node for Ruby case else branches 2026-06-15 11:42:13 +00:00
Sotiris Dragonas
7c11f19445 Merge branch 'main' into bazookamusic/cwe-1427 2026-06-15 10:15:16 +02:00
Sotiris Dragonas
7ae03377cd Add new MaD kinds 2026-06-15 11:14:25 +03:00
Owen Mansel-Chan
9c65082189 Fix MISSING alert 2026-06-15 00:14:52 +01:00
Owen Mansel-Chan
99538f0f07 Delete unused predicate (leftover from old implementation) 2026-06-12 22:21:07 +01:00
Owen Mansel-Chan
0dc95deca4 Test changes to investigate 2026-06-12 22:21:05 +01:00
Owen Mansel-Chan
0e902d0fe3 Fix captured variable liveness
- Extend synthetic uncertain reads to function exits of any function
  that writes a captured variable, not just the declaring function.
  This ensures writes to captured variables inside closures remain
  live (matching the old `v.isCaptured()` liveness shortcut).
- Uncomment toString overrides for SsaExplicitDefinition, SsaVariableCapture,
  SsaPhiNode, and SsaVariable to restore original output formats.
- Revert test expected files to pre-test-changes state matching the
  correct toString formats and capture variable results.

Agent-Logs-Url: https://github.com/github/codeql/sessions/6dbf9d42-b2e2-42a2-984b-8ea31df4e633

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
2026-06-12 22:21:03 +01:00
copilot-swe-agent[bot]
6ccbf16f3c Make Go use the shared SSA library (codeql.ssa.Ssa)
Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/codeql/sessions/b400ebd5-4095-401e-8811-fb550600b3c4
2026-06-12 22:21:02 +01:00
Owen Mansel-Chan
7a5219f06e Improve SSA tests for variables in closures 2026-06-12 22:21:00 +01:00
copilot-swe-agent[bot]
7a991e17b8 Initial plan 2026-06-12 22:20:58 +01:00
Owen Mansel-Chan
0b493c30cc Preemptively change toString() for SSA classes 2026-06-12 22:20:51 +01:00
Owen Mansel-Chan
434a99447e Add thorough tests, including one MISSING alert 2026-06-12 13:45:02 +01:00
Owen Mansel-Chan
d389ea4039 Convert sql-injection test to inline expectations 2026-06-12 13:44:56 +01:00
Owen Mansel-Chan
17b9a66895 Make alert coverage team the code owners for /actions/ 2026-06-12 10:17:12 +02:00
copilot-swe-agent[bot]
838d06c53f Fix changelog copy errors in change-notes and CHANGELOG.md files (codeql-cli-2.25.6) 2026-06-11 22:45:33 +02:00
Owen Mansel-Chan
913dcb1190 Add change note 2026-06-11 22:20:52 +02:00
Owen Mansel-Chan
befb557bfd Accept fixed MISSING tests 2026-06-11 15:44:20 +02:00
copilot-swe-agent[bot]
73bc2d70ae Model instance-attribute type flow
Use a field level step like JS and Ruby.
2026-06-11 14:48:55 +02:00
Sotiris Dragonas
17dbf03c6d Merge branch 'main' into bazookamusic/cwe-1427 2026-06-11 12:05:57 +02:00
BazookaMusic
ef5678708c Update not_included_in_qls.expected for promoted prompt injection queries
UserPromptInjection moved from experimental to stable (precision low, so not in any well-known suite); the old experimental path no longer exists.
2026-06-11 12:01:56 +02:00
BazookaMusic
7bd5abf809 Refine SystemPromptInjection alert message and move test to stable
Update the alert message to "This system prompt depends on a $@." matching the SQL injection query style, and move the test out of experimental into Security/CWE-1427 to mirror the stable query location.
2026-06-11 11:51:25 +02:00
BazookaMusic
e612db2ec9 Promote user prompt injection query to stable security
Move UserPromptInjection out of experimental into stable JavaScript security locations.

Set js/user-prompt-injection precision to low and remove experimental tagging.

Move supporting dataflow libraries, qhelp/examples, and tests to stable paths and update references.
2026-06-11 11:28:14 +02:00
copilot-swe-agent[bot]
a4585d8d94 Add test documenting missing PEP249 alerts for connection stored in self attribute 2026-06-11 05:48:40 +00:00
copilot-swe-agent[bot]
7795884946 Initial plan 2026-06-11 05:30:20 +00:00
Owen Mansel-Chan
990913519d Make comment clearer 2026-06-09 12:20:10 +02:00
Owen Mansel-Chan
e22f9fadd7 Fix mistakes in change notes
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-09 12:20:08 +02:00
Owen Mansel-Chan
071a0e3d7d Add change notes 2026-06-09 12:20:06 +02:00
Owen Mansel-Chan
a92349683e Deprecate FuncTypeExpr.getResultDecl()
It is unused in this library. It could easily be used incorrectly and
silently omit results when `getNumResult() > 1`.
2026-06-09 12:20:04 +02:00
Owen Mansel-Chan
8ce543bf4d Fix: getNumResult() was wrong in some cases
It was the number of result declarations, which is
different from the number of results when one
result declaration declares more than one
variable, as in `x, y int`.
2026-06-09 12:20:02 +02:00
Owen Mansel-Chan
da777a455d Improve QLDoc 2026-06-09 12:19:58 +02:00
Owen Mansel-Chan
f4f17b01c1 Fix result node and remove SPURIOUS test result 2026-06-09 12:19:56 +02:00
Owen Mansel-Chan
1c47084479 Add result node test with SPURIOUS result 2026-06-09 12:19:51 +02:00
Owen Mansel-Chan
c241049384 Add control flow test for result read steps 2026-06-09 12:19:49 +02:00
BazookaMusic
d0ffde8c45 Em-dash - of course :D 2026-06-08 14:03:12 +02:00
BazookaMusic
b6c951e90c Remove redundant file 2026-06-08 13:47:44 +02:00
BazookaMusic
2cb0851900 1. Rename AgentSDK -> AgentSdk
2. Remove redundant constant comparison barriers. This is already happening by default by the taint tracking library.
2026-06-08 12:55:52 +02:00
BazookaMusic
e370af6444 QLDoc + include the queries in the correct expected files per query suite 2026-06-08 12:38:28 +02:00
BazookaMusic
61be37d718 Formatting 2026-06-08 12:15:50 +02:00
BazookaMusic
da05992a09 Better document the new queries 2026-06-08 11:27:40 +02:00
Henry Mercer
9acf0d6dff Merge pull request #21946 from github/henrymercer/actions-tweak-query-name
Correct query metadata for `actions/untrusted-checkout/medium`
2026-06-05 09:54:27 +01:00
Henry Mercer
f4dc86e645 Correct query metadata for actions/untrusted-checkout/medium 2026-06-04 19:12:02 +01:00
Mathias Vorreiter Pedersen
44c8a97e2f JS: Update test output. 2026-06-04 17:55:09 +01:00
Mathias Vorreiter Pedersen
1d884a3979 QL: Add support for YAML comments. 2026-06-04 17:55:07 +01:00
Mathias Vorreiter Pedersen
8c35e089d8 Unified: Add support for YAML comments. 2026-06-04 17:55:04 +01:00
Mathias Vorreiter Pedersen
e1fde60988 Rust: Add upgrade and downgrade scripts. 2026-06-04 17:55:02 +01:00
Mathias Vorreiter Pedersen
1b29c12049 Rust: Add support for YAML comments. 2026-06-04 17:55:00 +01:00
Mathias Vorreiter Pedersen
d38091fe28 Ruby: Add upgrade and downgrade scripts. 2026-06-04 17:54:57 +01:00
Mathias Vorreiter Pedersen
303cb11609 Ruby: Add support for YAML comments. 2026-06-04 17:54:55 +01:00
Mathias Vorreiter Pedersen
b877943b42 Python: Add upgrade and downgrade scripts. 2026-06-04 17:54:53 +01:00
Mathias Vorreiter Pedersen
0aa1abe432 Python: Add support for YAML comments. 2026-06-04 17:54:48 +01:00
Mathias Vorreiter Pedersen
b6521e7c0e Actions: Support YAML comments. 2026-06-04 17:54:46 +01:00
Mathias Vorreiter Pedersen
e8f7454ea1 JS: Add tests. 2026-06-04 17:54:42 +01:00
Mathias Vorreiter Pedersen
3a90e8c77e JS: Add upgrade and downgrade scripts. 2026-06-04 17:54:40 +01:00
Mathias Vorreiter Pedersen
58b1a05985 JS: Support YAML comments. 2026-06-04 17:54:37 +01:00
BazookaMusic
078d15e165 add openrouter support 2026-06-04 16:42:49 +02:00
Mathias Vorreiter Pedersen
e87f7fb3f7 Shared: Support YAML comments. 2026-06-04 14:53:02 +01:00
Owen Mansel-Chan
c170002fb1 Update test output 2026-06-04 13:52:05 +01:00
Owen Mansel-Chan
14e3ee2fb0 Add change note 2026-06-04 13:39:42 +01:00
Owen Mansel-Chan
50e0354911 Tidy up comments in isSink 2026-06-04 13:39:36 +01:00
Owen Mansel-Chan
101812310c Inline isCloseCall into isSink 2026-06-04 13:39:24 +01:00
Owen Mansel-Chan
c87bfd5f28 Remove redundant call to isCloseSink 2026-06-04 13:09:10 +01:00
Owen Mansel-Chan
05e21adc53 Accept test changes 2026-06-04 13:09:07 +01:00
Owen Mansel-Chan
f67d0ea961 Go: Account for deferred Close in writable-file-close query
A deferred Close runs at function exit, but the CFG splices it in at the exit node where it can be reached along paths that never execute Sync. The previous dominance check therefore produced a false positive when a statement followed the if-block that registered the defer (e.g. deferredCloseWithSync2). For deferred closes, require instead that a handled Sync post-dominates the point where the defer is registered, which guarantees Sync runs before Close on every path on which Close is registered. Non-deferred closes keep the existing dominance check.
2026-06-04 13:09:05 +01:00
Owen Mansel-Chan
5217ede621 Go: Tidy up comments in writable-file-close query
Correct the doc for unhandledCall (it also matches expression statements where the result is discarded) and remove a stale commented-out line in isWritableFileHandle.
2026-06-04 13:09:03 +01:00
Owen Mansel-Chan
59908124c1 Add test showing limits of DeferStmt in CFG
There are paths to the exit of the function which go through the defer
statement and paths which don't, so we add an optional call to the
deferred function. This causes FPs in the query as it stands.
2026-06-04 12:21:38 +01:00
BazookaMusic
6c5c8e1c9b move system prompt injection to non-experimental 2026-05-20 10:48:07 +02:00
BazookaMusic
5ef09a102c add tests for langchain and remove wrong model for guardrails agent 2026-05-15 12:49:36 +02:00
BazookaMusic
fe7eabd56f Add run from agents into the user prompt and fix an issue with classifying it as a system prompt injection 2026-05-15 12:39:54 +02:00
BazookaMusic
535adc7a31 add barrier when data flows into user messages for system prompt detection, remove embeddings from user prompt injection query 2026-05-15 12:14:14 +02:00
BazookaMusic
9c136264de remove guardrails sanitizer for now 2026-05-13 13:37:44 +02:00
BazookaMusic
34da804aee Move structurally typed prompt injection sinks to Models as Data
Move OpenAI, Anthropic, Google GenAI, and LangChain sinks that are
structurally typed (identified by API name alone) into MaD YAML files.

Role-filtered sinks that require inspecting a sibling 'role' property
remain in QL code since MaD cannot express conditional logic.

Use two distinct sink kinds:
- user-prompt-injection: picked up by UserPromptInjection.ql
- system-prompt-injection: picked up by SystemPromptInjection.ql

New files:
- javascript/ql/lib/ext/openai.model.yml
- javascript/ql/lib/ext/anthropic.model.yml
- javascript/ql/lib/ext/google-genai.model.yml
- javascript/ql/lib/ext/langchain.model.yml
2026-05-13 11:08:25 +02:00
BazookaMusic
98379cffcb Documentation 2026-05-12 16:11:31 +02:00
BazookaMusic
9006ddb793 default threat model 2026-05-12 15:28:08 +02:00
BazookaMusic
74a3ba1f0d changes for spliting into system and user 2026-05-04 11:57:43 +02:00
BazookaMusic
0b7133c4ce JS: Add prompt injection detection (CWE-1427) for OpenAI, Anthropic, and Google GenAI SDKs
Add experimental CodeQL query detecting prompt injection vulnerabilities
in JavaScript/TypeScript applications using AI SDK libraries.

Modeled frameworks:
- openai (OpenAI, AzureOpenAI): responses, chat.completions, completions,
  images, embeddings, beta.assistants, beta.threads, audio APIs
- @openai/agents: Agent instructions, handoffDescription, run/Runner.run,
  asTool, tool()
- @anthropic-ai/sdk: messages.create, beta.messages.create,
  beta.agents.create/update
- @google/genai (GoogleGenAI): generateContent, generateContentStream,
  generateImages, editImage, chats, live.connect

Includes role-based filtering (system/developer/assistant/model roles)
and constant-comparison sanitizer guard.
2026-04-30 17:39:09 +02:00
648 changed files with 40428 additions and 5385 deletions

View File

@@ -2,7 +2,7 @@
* @github/code-scanning-alert-coverage
# CodeQL language libraries
/actions/ @github/codeql-dynamic
/actions/ @github/code-scanning-alert-coverage
/cpp/ @github/codeql-c-analysis
/csharp/ @github/codeql-csharp
/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor @github/code-scanning-language-coverage

View File

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

View File

@@ -2,7 +2,7 @@
### Minor Analysis Improvements
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
## 0.4.36

View File

@@ -2,4 +2,4 @@
### Minor Analysis Improvements
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.

View File

@@ -1920,3 +1920,5 @@ private YamlMappingLikeNode resolveMatrixAccessPath(
else result = resolveMatrixAccessPath(newRoot, rest)
)
}
class Comment = YamlComment;

View File

@@ -52,6 +52,12 @@ private module YamlSig implements LibYaml::InputSig {
class ParseErrorBase extends LocatableBase, @yaml_error {
string getMessage() { yaml_errors(this, result) }
}
class CommentBase extends LocatableBase, @yaml_comment {
string getText() { yaml_comments(this, result, _) }
override string toString() { yaml_comments(this, _, result) }
}
}
import LibYaml::Make<YamlSig>

View File

@@ -15,7 +15,7 @@
### Bug Fixes
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
## 0.6.28

View File

@@ -1,8 +1,8 @@
/**
* @name Checkout of untrusted code in a trusted context
* @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets.
* @name Checkout of untrusted code in a non-privileged context
* @description Checking out and running the build script from a fork executes untrusted code. Even in a
* non-privileged workflow, this can be abused, for example to compromise self-hosted runners
* or to poison caches and artifacts that are later consumed by privileged workflows.
* @kind problem
* @problem.severity warning
* @precision medium
@@ -20,4 +20,4 @@ from PRHeadCheckoutStep checkout
where
// the checkout occurs in a non-privileged context
inNonPrivilegedContext(checkout)
select checkout, "Potential unsafe checkout of untrusted pull request on privileged workflow."
select checkout, "Potential unsafe checkout of untrusted pull request on non-privileged workflow."

View File

@@ -0,0 +1,4 @@
---
category: queryMetadata
---
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.

View File

@@ -15,4 +15,4 @@
### Bug Fixes
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.

View File

@@ -1,10 +1,10 @@
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |

View File

@@ -135,7 +135,7 @@ namespace Semmle.Autobuild.CSharp.Tests
if (!EnumerateFiles.TryGetValue(dir, out var str))
throw new ArgumentException("Missing EnumerateFiles " + dir);
return str.Split("\n").Select(p => PathCombine(dir, p));
return str.Split("\n").Select(p => PathJoin(dir, p));
}
public IDictionary<string, string> EnumerateDirectories { get; } = new Dictionary<string, string>();
@@ -147,7 +147,7 @@ namespace Semmle.Autobuild.CSharp.Tests
return string.IsNullOrEmpty(str)
? Enumerable.Empty<string>()
: str.Split("\n").Select(p => PathCombine(dir, p));
: str.Split("\n").Select(p => PathJoin(dir, p));
}
public bool IsWindows { get; set; }
@@ -170,7 +170,7 @@ namespace Semmle.Autobuild.CSharp.Tests
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
public string PathCombine(params string[] parts)
public string PathJoin(params string[] parts)
{
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
}

View File

@@ -109,7 +109,7 @@ namespace Semmle.Autobuild.CSharp
=> WithDotNet(builder, ensureDotNetAvailable: false, (_, env) => f(env));
private static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
dotNetPath is not null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
dotNetPath is not null ? actions.PathJoin(dotNetPath, "dotnet") : "dotnet";
private static CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
{

View File

@@ -158,7 +158,7 @@ namespace Semmle.Autobuild.Cpp.Tests
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
string IBuildActions.PathCombine(params string[] parts)
string IBuildActions.PathJoin(params string[] parts)
{
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
}

View File

@@ -108,7 +108,7 @@ namespace Semmle.Autobuild.Shared
/// </summary>
/// <param name="path">The relative path.</param>
/// <returns>True iff the path was found.</returns>
public bool HasRelativePath(string path) => HasPath(Actions.PathCombine(RootDirectory, path));
public bool HasRelativePath(string path) => HasPath(Actions.PathJoin(RootDirectory, path));
/// <summary>
/// List of project/solution files to build.

View File

@@ -32,7 +32,7 @@ namespace Semmle.Autobuild.Shared
yield break;
// Attempt to use vswhere to find installations of Visual Studio
var vswhere = actions.PathCombine(programFilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
var vswhere = actions.PathJoin(programFilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
if (actions.FileExists(vswhere))
{
@@ -51,14 +51,14 @@ namespace Semmle.Autobuild.Shared
if (majorVersion < 15)
{
// Visual Studio 2015 and below
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\vcvarsall.bat"), majorVersion);
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\vcvarsall.bat"), majorVersion);
}
else
{
// Visual Studio 2017 and above
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars32.bat"), majorVersion);
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars64.bat"), majorVersion);
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"Common7\Tools\VsDevCmd.bat"), majorVersion);
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars32.bat"), majorVersion);
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars64.bat"), majorVersion);
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"Common7\Tools\VsDevCmd.bat"), majorVersion);
}
}
// else: Skip installation without a version
@@ -68,10 +68,10 @@ namespace Semmle.Autobuild.Shared
}
// vswhere not installed or didn't run correctly - return legacy Visual Studio versions
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 14.0\VC\vcvarsall.bat"), 14);
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 12.0\VC\vcvarsall.bat"), 12);
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 11.0\VC\vcvarsall.bat"), 11);
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 10.0\VC\vcvarsall.bat"), 10);
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 14.0\VC\vcvarsall.bat"), 14);
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 12.0\VC\vcvarsall.bat"), 12);
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 11.0\VC\vcvarsall.bat"), 11);
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 10.0\VC\vcvarsall.bat"), 10);
}
/// <summary>

View File

@@ -60,7 +60,7 @@ namespace Semmle.Autobuild.Shared
// Use `nuget.exe` from source code repo, if present, otherwise first attempt with global
// `nuget` command, and if that fails, attempt to download `nuget.exe` from nuget.org
var nuget = builder.GetFilename("nuget.exe").Select(t => t.Item1).FirstOrDefault() ?? "nuget";
var nugetDownloadPath = builder.Actions.PathCombine(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out _), ".nuget", "nuget.exe");
var nugetDownloadPath = builder.Actions.PathJoin(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out _), ".nuget", "nuget.exe");
var nugetDownloaded = false;
var ret = BuildScript.Success;

View File

@@ -107,8 +107,9 @@ namespace Semmle.Autobuild.Shared
continue;
}
var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
ret.Add(new Project<TAutobuildOptions>(builder, builder.Actions.PathCombine(DirectoryName, includePath)));
var includePath = builder.Actions.PathJoin(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
var path = Path.IsPathRooted(includePath) ? includePath : builder.Actions.PathJoin(DirectoryName, includePath);
ret.Add(new Project<TAutobuildOptions>(builder, path));
}
return ret;
});

View File

@@ -79,7 +79,7 @@ namespace Semmle.Autobuild.Shared
includedProjects = solution.ProjectsInOrder
.Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
.Select(p => builder.Actions.PathCombine(DirectoryName, builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
.Select(p => builder.Actions.PathJoin(DirectoryName, builder.Actions.PathJoin(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
.Select(p => new Project<TAutobuildOptions>(builder, p))
.ToArray();
}

View File

@@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return;
}
var path = Path.Combine(p, ParseFilePath(d));
var path = Path.Join(p, ParseFilePath(d));
Paths.Add(path);
Packages.Add(GetPackageName(p));
}

View File

@@ -75,7 +75,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
this.diagnosticsWriter = new DiagnosticsStream(Path.Combine(
this.diagnosticsWriter = new DiagnosticsStream(Path.Join(
diagDirEnv ?? "",
$"dependency-manager-{DateTime.UtcNow:yyyyMMddHHmm}-{Environment.ProcessId}.jsonc"));
this.sourceDir = new DirectoryInfo(srcDir);
@@ -327,7 +327,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void RemoveNugetPackageReference(string packagePrefix, ISet<AssemblyLookupLocation> dllLocations)
{
var packageFolder = nugetPackageRestorer.PackageDirectory.DirInfo.FullName.ToLowerInvariant();
var packagePathPrefix = Path.Combine(packageFolder, packagePrefix.ToLowerInvariant());
var packagePathPrefix = Path.Join(packageFolder, packagePrefix.ToLowerInvariant());
var toRemove = dllLocations.Where(s => s.Path.StartsWith(packagePathPrefix, StringComparison.InvariantCultureIgnoreCase));
foreach (var path in toRemove)
{

View File

@@ -31,7 +31,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet"), dependabotProxy), logger, dotNetPath is null, tempWorkingDirectory) { }
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) : this(new DotNetCliInvoker(logger, Path.Join(dotNetPath ?? string.Empty, "dotnet"), dependabotProxy), logger, dotNetPath is null, tempWorkingDirectory) { }
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, bool runDotnetInfo) => new DotNet(dotnetCliInvoker, logger, runDotnetInfo);
@@ -73,7 +73,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var path = ".empty";
if (tempWorkingDirectory != null)
{
path = Path.Combine(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
path = Path.Join(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
Directory.CreateDirectory(path);
}
@@ -303,7 +303,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
else
{
var dotnetInstallPath = actions.PathCombine(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
var dotnetInstallPath = actions.PathJoin(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
var downloadDotNetInstallSh = BuildScript.DownloadFile(
"https://dot.net/v1/dotnet-install.sh",
dotnetInstallPath,
@@ -339,7 +339,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
};
}
var dotnetInfo = InfoScript(actions, actions.PathCombine(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
var dotnetInfo = InfoScript(actions, actions.PathJoin(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
Func<string, BuildScript> getInstallAndVerify = version =>
// run `dotnet --info` after install, to check that it executes successfully
@@ -384,7 +384,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
public static BuildScript WithDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, bool ensureDotNetAvailable, string? version, Func<string?, BuildScript> f)
{
var installDir = actions.PathCombine(tempWorkingDirectory, ".dotnet");
var installDir = actions.PathJoin(tempWorkingDirectory, ".dotnet");
var installScript = DownloadDotNet(actions, logger, files, tempWorkingDirectory, shouldCleanUp, installDir, version, ensureDotNetAvailable);
return BuildScript.Bind(installScript, installed =>
{

View File

@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private string FullVersion =>
version.ToString();
public string FullPath => Path.Combine(dir, FullVersion);
public string FullPath => Path.Join(dir, FullVersion);
/**
* The full path to the reference assemblies for this runtime.
@@ -33,7 +33,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
directories[^2] = "packs";
directories[^1] = $"{directories[^1]}.Ref";
return Path.Combine(string.Join(Path.DirectorySeparatorChar, directories), FullVersion, "ref");
return Path.Join(string.Join(Path.DirectorySeparatorChar, directories), FullVersion, "ref");
}
return null;
}

View File

@@ -1,304 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
/// <summary>
/// Manage the downloading of NuGet packages with nuget.exe.
/// Locates packages in a source tree and downloads all of the
/// referenced assemblies to a temp folder.
/// </summary>
internal class NugetExeWrapper : IDisposable
{
private readonly string? nugetExe;
private readonly Semmle.Util.Logging.ILogger logger;
public int PackageCount => fileProvider.PackagesConfigs.Count;
private readonly string? backupNugetConfig;
private readonly string? nugetConfigPath;
private readonly FileProvider fileProvider;
/// <summary>
/// The packages directory.
/// This will be in the user-specified or computed Temp location
/// so as to not trample the source tree.
/// </summary>
private readonly DependencyDirectory packageDirectory;
/// <summary>
/// Create the package manager for a specified source tree.
/// </summary>
public NugetExeWrapper(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
{
this.fileProvider = fileProvider;
this.packageDirectory = packageDirectory;
this.logger = logger;
if (fileProvider.PackagesConfigs.Count > 0)
{
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
nugetExe = ResolveNugetExe();
if (HasNoPackageSource() && useDefaultFeed())
{
// We only modify or add a top level nuget.config file
nugetConfigPath = Path.Combine(fileProvider.SourceDir.FullName, "nuget.config");
try
{
if (File.Exists(nugetConfigPath))
{
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out _);
do
{
backupNugetConfig = Path.Combine(tempFolderPath, Path.GetRandomFileName());
}
while (File.Exists(backupNugetConfig));
File.Copy(nugetConfigPath, backupNugetConfig, true);
}
else
{
File.WriteAllText(nugetConfigPath,
"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
</packageSources>
</configuration>
""");
}
AddDefaultPackageSource(nugetConfigPath);
}
catch (Exception e)
{
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
}
}
}
}
/// <summary>
/// Tries to find the location of `nuget.exe`. It looks for
/// - the environment variable specifying a location,
/// - files in the repository,
/// - tries to resolve nuget from the PATH, or
/// - downloads it if it is not found.
/// </summary>
private string ResolveNugetExe()
{
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
if (!string.IsNullOrEmpty(envVarPath))
{
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
return envVarPath;
}
try
{
return DownloadNugetExe(fileProvider.SourceDir.FullName);
}
catch (Exception exc)
{
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
}
var nugetExesInRepo = fileProvider.NugetExes;
if (nugetExesInRepo.Count > 1)
{
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
}
if (nugetExesInRepo.Count > 0)
{
var path = nugetExesInRepo.First();
logger.LogInfo($"Using nuget.exe from path '{path}'");
return path;
}
var executableName = Win32.IsWindows() ? "nuget.exe" : "nuget";
var nugetPath = FileUtils.FindProgramOnPath(executableName);
if (nugetPath is not null)
{
nugetPath = Path.Combine(nugetPath, executableName);
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
return nugetPath;
}
throw new Exception("Could not find or download nuget.exe.");
}
private string DownloadNugetExe(string sourceDir)
{
var directory = Path.Combine(sourceDir, ".nuget");
var nuget = Path.Combine(directory, "nuget.exe");
// Nuget.exe already exists in the .nuget directory.
if (File.Exists(nuget))
{
logger.LogInfo($"Found nuget.exe at {nuget}");
return nuget;
}
Directory.CreateDirectory(directory);
logger.LogInfo("Attempting to download nuget.exe");
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget, logger);
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
return nuget;
}
private bool RunWithMono => !Win32.IsWindows() && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
/// <summary>
/// Restore all packages in the specified packages.config file.
/// </summary>
/// <param name="packagesConfig">The packages.config file.</param>
private bool TryRestoreNugetPackage(string packagesConfig)
{
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
/* Use nuget.exe to install a package.
* Note that there is a clutch of NuGet assemblies which could be used to
* invoke this directly, which would arguably be nicer. However they are
* really unwieldy and this solution works for now.
*/
string exe, args;
if (RunWithMono)
{
exe = "mono";
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
}
else
{
exe = nugetExe!;
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
}
var pi = new ProcessStartInfo(exe, args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
var threadId = Environment.CurrentManagedThreadId;
void onOut(string s) => logger.LogDebug(s, threadId);
void onError(string s) => logger.LogError(s, threadId);
var exitCode = pi.ReadOutput(out _, onOut, onError);
if (exitCode != 0)
{
logger.LogError($"Command {pi.FileName} {pi.Arguments} failed with exit code {exitCode}");
return false;
}
else
{
logger.LogInfo($"Restored file \"{packagesConfig}\"");
return true;
}
}
/// <summary>
/// Download the packages to the temp folder.
/// </summary>
public int InstallPackages()
{
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
}
private bool HasNoPackageSource()
{
if (Win32.IsWindows())
{
return false;
}
try
{
logger.LogInfo("Checking if default package source is available...");
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
if (stdout.All(line => line != "No sources found."))
{
return false;
}
return true;
}
catch (Exception e)
{
logger.LogWarning($"Failed to check if default package source is added: {e}");
return false;
}
}
private void RunMonoNugetCommand(string command, out IList<string> stdout)
{
string exe, args;
if (RunWithMono)
{
exe = "mono";
args = $"\"{nugetExe}\" {command}";
}
else
{
exe = nugetExe!;
args = command;
}
var pi = new ProcessStartInfo(exe, args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
var threadId = Environment.CurrentManagedThreadId;
void onOut(string s) => logger.LogDebug(s, threadId);
void onError(string s) => logger.LogError(s, threadId);
pi.ReadOutput(out stdout, onOut, onError);
}
private void AddDefaultPackageSource(string nugetConfig)
{
logger.LogInfo("Adding default package source...");
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
}
public void Dispose()
{
if (nugetConfigPath is null)
{
return;
}
try
{
if (backupNugetConfig is null)
{
logger.LogInfo("Removing nuget.config file");
File.Delete(nugetConfigPath);
return;
}
logger.LogInfo("Reverting nuget.config file content");
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
using (var backup = File.OpenRead(backupNugetConfig))
using (var current = File.OpenWrite(nugetConfigPath))
{
current.SetLength(0); // Truncate file
backup.CopyTo(current); // Restore original content
}
logger.LogInfo("Deleting backup nuget.config file");
File.Delete(backupNugetConfig);
}
catch (Exception exc)
{
logger.LogError($"Failed to restore original nuget.config file: {exc}");
}
}
}
}

View File

@@ -161,13 +161,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
reachableFeeds.UnionWith(reachableInheritedFeeds);
}
using (var nuget = new NugetExeWrapper(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
using (var packagesConfigRestore = PackagesConfigRestoreFactory.Create(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
{
var count = nuget.InstallPackages();
var count = packagesConfigRestore.InstallPackages();
if (nuget.PackageCount > 0)
if (packagesConfigRestore.PackageCount > 0)
{
compilationInfoContainer.CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
compilationInfoContainer.CompilationInfos.Add(("packages.config files", packagesConfigRestore.PackageCount.ToString()));
compilationInfoContainer.CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
}
}
@@ -209,7 +209,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var paths = dependencies
.Paths
.Select(d => Path.Combine(PackageDirectory.DirInfo.FullName, d))
.Select(d => Path.Join(PackageDirectory.DirInfo.FullName, d))
.ToList();
assemblyLookupLocations.UnionWith(paths.Select(p => new AssemblyLookupLocation(p)));
@@ -527,7 +527,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var sb = new StringBuilder();
fallbackNugetFeeds.ForEach((feed, index) => sb.AppendLine($"<add key=\"feed{index}\" value=\"{feed}\" />"));
var nugetConfigPath = Path.Combine(folderPath, "nuget.config");
var nugetConfigPath = Path.Join(folderPath, "nuget.config");
logger.LogInfo($"Creating fallback nuget.config file {nugetConfigPath}.");
File.WriteAllText(nugetConfigPath,
$"""
@@ -1052,7 +1052,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
private static string ComputeTempDirectoryPath(string subfolderName)
{
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName);
return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName);
}
/// <summary>
@@ -1060,7 +1060,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
private static string ComputeTempDirectoryPath(string srcDir, string subfolderName)
{
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
}
}
}

View File

@@ -0,0 +1,368 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal interface IPackagesConfigRestore : IDisposable
{
/// <summary>
/// The number of packages.config files found in the source tree.
/// </summary>
int PackageCount { get; }
/// <summary>
/// Download the packages to the temp folder.
/// </summary>
int InstallPackages();
}
/// <summary>
/// Factory for creating a package manager to restore NuGet packages referenced in packages.config files.
/// If the environment doesn't support using nuget.exe to restore packages from packages.config files, a no-op implementation is returned.
/// It is worth noting that for macOS and Linux, nuget.exe is used with mono. However, mono is being deprecated and the last GitHub images
/// to contain mono are:
/// - Ubuntu 22.04
/// - macOS 14
///
/// If the packages from the packages.config files are not restored with the packages.config restore functionality below, there is a subsequent
/// step that still may succeed in restoring the packages without the help of nuget.exe (by attempting to restore using dotnet).
/// </summary>
internal class PackagesConfigRestoreFactory
{
public static IPackagesConfigRestore Create(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
{
if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMonoInstalled())
{
return new NugetExeWrapper(fileProvider, packageDirectory, logger, useDefaultFeed);
}
return new NoOpPackagesConfig(fileProvider, logger);
}
/// <summary>
/// Manage the downloading of NuGet packages with nuget.exe.
/// Locates packages in a source tree and downloads all of the
/// referenced assemblies to a temp folder.
/// </summary>
private class NugetExeWrapper : IPackagesConfigRestore
{
private readonly string? nugetExe;
private readonly Semmle.Util.Logging.ILogger logger;
public int PackageCount => fileProvider.PackagesConfigs.Count;
private readonly string? backupNugetConfig;
private readonly string? nugetConfigPath;
private readonly FileProvider fileProvider;
/// <summary>
/// The packages directory.
/// This will be in the user-specified or computed Temp location
/// so as to not trample the source tree.
/// </summary>
private readonly DependencyDirectory packageDirectory;
private bool IsWindows => SystemBuildActions.Instance.IsWindows();
/// <summary>
/// Create the package manager for a specified source tree.
/// </summary>
public NugetExeWrapper(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
{
this.fileProvider = fileProvider;
this.packageDirectory = packageDirectory;
this.logger = logger;
if (fileProvider.PackagesConfigs.Count > 0)
{
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
nugetExe = ResolveNugetExe();
if (!HasPackageSource() && useDefaultFeed())
{
// We only modify or add a top level nuget.config file
nugetConfigPath = Path.Join(fileProvider.SourceDir.FullName, "nuget.config");
try
{
if (File.Exists(nugetConfigPath))
{
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out _);
do
{
backupNugetConfig = Path.Join(tempFolderPath, Path.GetRandomFileName());
}
while (File.Exists(backupNugetConfig));
File.Copy(nugetConfigPath, backupNugetConfig, true);
}
else
{
File.WriteAllText(nugetConfigPath,
"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
</packageSources>
</configuration>
""");
}
AddDefaultPackageSource(nugetConfigPath);
}
catch (Exception e)
{
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
}
}
}
}
/// <summary>
/// Tries to find the location of `nuget.exe`. It looks for
/// - the environment variable specifying a location,
/// - files in the repository,
/// - tries to resolve nuget from the PATH, or
/// - downloads it if it is not found.
/// </summary>
private string ResolveNugetExe()
{
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
if (!string.IsNullOrEmpty(envVarPath))
{
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
return envVarPath;
}
try
{
return DownloadNugetExe(fileProvider.SourceDir.FullName);
}
catch (Exception exc)
{
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
}
var nugetExesInRepo = fileProvider.NugetExes;
if (nugetExesInRepo.Count > 1)
{
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
}
if (nugetExesInRepo.Count > 0)
{
var path = nugetExesInRepo.First();
logger.LogInfo($"Using nuget.exe from path '{path}'");
return path;
}
var executableName = IsWindows ? "nuget.exe" : "nuget";
var nugetPath = FileUtils.FindProgramOnPath(executableName);
if (nugetPath is not null)
{
nugetPath = Path.Join(nugetPath, executableName);
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
return nugetPath;
}
throw new Exception("Could not find or download nuget.exe.");
}
private string DownloadNugetExe(string sourceDir)
{
var directory = Path.Join(sourceDir, ".nuget");
var nuget = Path.Join(directory, "nuget.exe");
// Nuget.exe already exists in the .nuget directory.
if (File.Exists(nuget))
{
logger.LogInfo($"Found nuget.exe at {nuget}");
return nuget;
}
Directory.CreateDirectory(directory);
logger.LogInfo("Attempting to download nuget.exe");
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget, logger);
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
return nuget;
}
private bool RunWithMono => !IsWindows && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
/// <summary>
/// Restore all packages in the specified packages.config file.
/// </summary>
/// <param name="packagesConfig">The packages.config file.</param>
private bool TryRestoreNugetPackage(string packagesConfig)
{
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
/* Use nuget.exe to install a package.
* Note that there is a clutch of NuGet assemblies which could be used to
* invoke this directly, which would arguably be nicer. However they are
* really unwieldy and this solution works for now.
*/
string exe, args;
if (RunWithMono)
{
exe = "mono";
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
}
else
{
exe = nugetExe!;
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
}
var pi = new ProcessStartInfo(exe, args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
var threadId = Environment.CurrentManagedThreadId;
void onOut(string s) => logger.LogDebug(s, threadId);
void onError(string s) => logger.LogError(s, threadId);
var exitCode = pi.ReadOutput(out _, onOut, onError);
if (exitCode != 0)
{
logger.LogError($"Command {pi.FileName} {pi.Arguments} failed with exit code {exitCode}");
return false;
}
else
{
logger.LogInfo($"Restored file \"{packagesConfig}\"");
return true;
}
}
/// <summary>
/// Download the packages to the temp folder.
/// </summary>
public int InstallPackages()
{
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
}
private bool HasPackageSource()
{
if (IsWindows)
{
return true;
}
try
{
logger.LogInfo("Checking if default package source is available...");
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
if (stdout.All(line => line != "No sources found."))
{
return true;
}
return false;
}
catch (Exception e)
{
logger.LogWarning($"Failed to check if default package source is added: {e}");
return true;
}
}
private void RunMonoNugetCommand(string command, out IList<string> stdout)
{
string exe, args;
if (RunWithMono)
{
exe = "mono";
args = $"\"{nugetExe}\" {command}";
}
else
{
exe = nugetExe!;
args = command;
}
var pi = new ProcessStartInfo(exe, args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
var threadId = Environment.CurrentManagedThreadId;
void onOut(string s) => logger.LogDebug(s, threadId);
void onError(string s) => logger.LogError(s, threadId);
pi.ReadOutput(out stdout, onOut, onError);
}
private void AddDefaultPackageSource(string nugetConfig)
{
logger.LogInfo("Adding default package source...");
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
}
public void Dispose()
{
if (nugetConfigPath is null)
{
return;
}
try
{
if (backupNugetConfig is null)
{
logger.LogInfo("Removing nuget.config file");
File.Delete(nugetConfigPath);
return;
}
logger.LogInfo("Reverting nuget.config file content");
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
using (var backup = File.OpenRead(backupNugetConfig))
using (var current = File.OpenWrite(nugetConfigPath))
{
current.SetLength(0); // Truncate file
backup.CopyTo(current); // Restore original content
}
logger.LogInfo("Deleting backup nuget.config file");
File.Delete(backupNugetConfig);
}
catch (Exception exc)
{
logger.LogError($"Failed to restore original nuget.config file: {exc}");
}
}
}
private class NoOpPackagesConfig : IPackagesConfigRestore
{
private readonly Semmle.Util.Logging.ILogger logger;
private readonly FileProvider fileProvider;
public NoOpPackagesConfig(FileProvider fileProvider, Semmle.Util.Logging.ILogger logger)
{
this.fileProvider = fileProvider;
this.logger = logger;
}
public int PackageCount => fileProvider.PackagesConfigs.Count;
public int InstallPackages()
{
if (PackageCount > 0)
{
logger.LogInfo("Found packages.config files, but nuget.exe cannot be used to restore packages on this platform. Skipping restore of packages.config files.");
}
return 0;
}
public void Dispose() { }
}
}
}

View File

@@ -79,7 +79,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
string[] monoDirs = monoPath is not null
? [Path.GetFullPath(Path.Combine(monoPath, "..", "lib", "mono")), monoPath]
? [Path.GetFullPath(Path.Join(monoPath, "..", "lib", "mono")), monoPath]
: ["/usr/lib/mono", "/usr/local/mono", "/usr/local/bin/mono", @"C:\Program Files\Mono\lib\mono"];
var monoDir = monoDirs.FirstOrDefault(Directory.Exists);

View File

@@ -63,7 +63,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return null;
}
var path = Path.Combine(version.FullPath, "Roslyn", "bincore", "csc.dll");
var path = Path.Join(version.FullPath, "Roslyn", "bincore", "csc.dll");
logger.LogDebug($"Source generator CSC: '{path}'");
if (!File.Exists(path))
{

View File

@@ -41,10 +41,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
.Replace('\\', '/'); // Ensure we're generating the same hash regardless of the OS
var name = FileUtils.ComputeHash($"{relativePathToCsProj}\n{this.GetType().Name}");
using var tempDir = new TemporaryDirectory(Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), "source-generator"), "source generator temporary", logger);
var analyzerConfigPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.txt");
var dllPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.dll");
var cscArgsPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.rsp");
var outputFolder = Path.Combine(targetDir, name);
var analyzerConfigPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.txt");
var dllPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.dll");
var cscArgsPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.rsp");
var outputFolder = Path.Join(targetDir, name);
Directory.CreateDirectory(outputFolder);
logger.LogInfo("Producing analyzer config content.");
GenerateAnalyzerConfig(additionalFiles, csprojFile, analyzerConfigPath);

View File

@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
throw new Exception("No SDK path available.");
}
SourceGeneratorFolder = Path.Combine(sdkPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
SourceGeneratorFolder = Path.Join(sdkPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
this.logger.LogInfo($"Razor source generator folder: {SourceGeneratorFolder}");
if (!Directory.Exists(SourceGeneratorFolder))
{

View File

@@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (usings.Count > 0)
{
var tempDir = GetTemporaryWorkingDirectory("implicitUsings");
var path = Path.Combine(tempDir, "GlobalUsings.g.cs");
var path = Path.Join(tempDir, "GlobalUsings.g.cs");
using (var writer = new StreamWriter(path))
{
writer.WriteLine("// <auto-generated/>");

View File

@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var nugetFolder = nugetPackageRestorer.TryRestore("Microsoft.CodeAnalysis.ResxSourceGenerator");
if (nugetFolder is not null)
{
sourceGeneratorFolder = System.IO.Path.Combine(nugetFolder, "analyzers", "dotnet", "cs");
sourceGeneratorFolder = System.IO.Path.Join(nugetFolder, "analyzers", "dotnet", "cs");
}
}
catch (Exception e)

View File

@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
protected string GetTemporaryWorkingDirectory(string subfolder)
{
var temp = Path.Combine(tempWorkingDirectory.ToString(), subfolder);
var temp = Path.Join(tempWorkingDirectory.ToString(), subfolder);
Directory.CreateDirectory(temp);
return temp;

View File

@@ -23,7 +23,9 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
}
else if (isSpecificCatchClause) // A catch clause of the form 'catch(Ex) { ... }'
{
trapFile.catch_type(this, Type.Create(Context, Context.GetType(Stmt.Declaration!.Type)).TypeRef, true);
var type = Type.Create(Context, Context.GetType(Stmt.Declaration!.Type));
trapFile.catch_type(this, type.TypeRef, true);
TypeMention.Create(Context, Stmt.Declaration!.Type, this, type);
}
else // A catch clause of the form 'catch { ... }'
{

View File

@@ -67,7 +67,7 @@ namespace Semmle.Extraction.CSharp
return;
}
var mscorlibExists = File.Exists(Path.Combine(compilerDir, "mscorlib.dll"));
var mscorlibExists = File.Exists(Path.Join(compilerDir, "mscorlib.dll"));
if (specifiedFramework is null && mscorlibExists)
{
@@ -107,7 +107,7 @@ namespace Semmle.Extraction.CSharp
/// <summary>
/// The file csc.rsp.
/// </summary>
private string CscRsp => Path.Combine(FrameworkPath, csc_rsp);
private string CscRsp => Path.Join(FrameworkPath, csc_rsp);
/// <summary>
/// Should we skip extraction?

View File

@@ -680,7 +680,7 @@ namespace Semmle.Extraction.CSharp
{
try
{
var fullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
var fullPath = Path.GetFullPath(Path.Join(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
ExtractionContext.Logger.LogDebug($"Found relative path in line mapping: '{mappedToPath}', interpreting it as '{fullPath}'");
mappedToPath = fullPath;

View File

@@ -159,7 +159,11 @@ namespace Semmle.Extraction.CSharp
return null;
}
return Path.GetFullPath(Path.Combine(projDir?.FullName ?? string.Empty, Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file));
var normalized = Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file;
var path = projDir is not null && !Path.IsPathRooted(normalized)
? Path.Join(projDir.FullName, normalized)
: normalized;
return Path.GetFullPath(path);
}
private readonly string[] references;

View File

@@ -210,7 +210,7 @@ namespace Semmle.Extraction.CSharp
TracingAnalyser.GetOutputName(compilation, args),
compilation,
generatedSyntaxTrees,
Path.Combine(compilationIdentifierPath, diagnosticName),
Path.Join(compilationIdentifierPath, diagnosticName),
options),
() => { });
@@ -377,7 +377,7 @@ namespace Semmle.Extraction.CSharp
else
{
var composed = referencePaths.Value
.Select(path => Path.Combine(path, clref.Reference))
.Select(path => Path.Join(path, clref.Reference))
.Where(path => File.Exists(path))
.Select(path => analyser.PathCache.GetCanonicalPath(path))
.FirstOrDefault();
@@ -559,13 +559,13 @@ namespace Semmle.Extraction.CSharp
/// Gets the path to the `csharp.log` file written to by the C# extractor.
/// </summary>
public static string GetCSharpLogPath() =>
Path.Combine(GetCSharpLogDirectory(), "csharp.log");
Path.Join(GetCSharpLogDirectory(), "csharp.log");
/// <summary>
/// Gets the path to a `csharp.{hash}.txt` file written to by the C# extractor.
/// </summary>
public static string GetCSharpArgsLogPath(string hash) =>
Path.Combine(GetCSharpLogDirectory(), $"csharp.{hash}.txt");
Path.Join(GetCSharpLogDirectory(), $"csharp.{hash}.txt");
/// <summary>
/// Gets a list of all `csharp.{hash}.txt` files currently written to the log directory.

View File

@@ -131,7 +131,7 @@ namespace Semmle.Extraction.CSharp
return Path.ChangeExtension(entryPointFilename, ".exe");
}
return Path.Combine(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
return Path.Join(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
}
private int LogDiagnostics()

View File

@@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp
* Although GetRandomFileName() is cryptographically secure,
* there's a tiny chance the file could already exists.
*/
tmpFile = Path.Combine(tempPath, Path.GetRandomFileName());
tmpFile = Path.Join(tempPath, Path.GetRandomFileName());
}
while (File.Exists(tmpFile));

View File

@@ -82,13 +82,13 @@ namespace SemmleTests.Semmle.Util
[Fact]
public void CanonicalPathMissingFile()
{
Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "NOSUCHFILE"), cache.GetCanonicalPath("NOSUCHFILE"));
Assert.Equal(Path.Join(Directory.GetCurrentDirectory(), "NOSUCHFILE"), cache.GetCanonicalPath("NOSUCHFILE"));
}
[Fact]
public void CanonicalPathMissingAbsolutePath()
{
Assert.Equal(Path.Combine(root, "no", "such", "file"), cache.GetCanonicalPath(Path.Combine(root, "no", "such", "file")));
Assert.Equal(Path.Join(root, "no", "such", "file"), cache.GetCanonicalPath(Path.Join(root, "no", "such", "file")));
if (Win32.IsWindows())
Assert.Equal(@"C:\Windows\no\such\file", cache.GetCanonicalPath(@"C:\windOws\no\such\file"));
@@ -97,7 +97,7 @@ namespace SemmleTests.Semmle.Util
[Fact]
public void CanonicalPathMissingRelativePath()
{
Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "NO", "SUCH"), cache.GetCanonicalPath(Path.Combine("NO", "SUCH")));
Assert.Equal(Path.Join(Directory.GetCurrentDirectory(), "NO", "SUCH"), cache.GetCanonicalPath(Path.Join("NO", "SUCH")));
}
[Fact]
@@ -125,7 +125,7 @@ namespace SemmleTests.Semmle.Util
public void CanonicalPathDots()
{
var abcPath = Path.GetFullPath("abc");
Assert.Equal(abcPath, cache.GetCanonicalPath(Path.Combine("foo", ".", "..", "abc")));
Assert.Equal(abcPath, cache.GetCanonicalPath(Path.Join("foo", ".", "..", "abc")));
}
[Fact]

View File

@@ -14,20 +14,20 @@ namespace SemmleTests.Semmle.Util
public sealed class LongPaths
{
private static readonly string tmpDir = Environment.GetEnvironmentVariable("TEST_TMPDIR") ?? Path.GetTempPath();
private static readonly string longPathDir = Path.Combine(tmpDir, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
private static readonly string longPathDir = Path.Join(tmpDir, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"ccccccccccccccccccccccccccccccc", "ddddddddddddddddddddddddddddddddddddd", "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "fffffffffffffffffffffffffffffffff",
"ggggggggggggggggggggggggggggggggggg", "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
private static string MakeLongPath()
{
var uniquePostfix = Guid.NewGuid().ToString("N");
return Path.Combine(longPathDir, $"iiiiiiiiiiiiiiii{uniquePostfix}.txt");
return Path.Join(longPathDir, $"iiiiiiiiiiiiiiii{uniquePostfix}.txt");
}
private static string MakeShortPath()
{
var uniquePostfix = Guid.NewGuid().ToString("N");
return Path.Combine(tmpDir, $"test{uniquePostfix}.txt");
return Path.Join(tmpDir, $"test{uniquePostfix}.txt");
}
public LongPaths()
@@ -62,7 +62,7 @@ namespace SemmleTests.Semmle.Util
[Fact]
public void ParentDirectory()
{
Assert.Equal("abc", Path.GetDirectoryName(Path.Combine("abc", "def")));
Assert.Equal("abc", Path.GetDirectoryName(Path.Join("abc", "def")));
Assert.Equal(Win32.IsWindows() ? "\\" : "/", Path.GetDirectoryName($@"{Path.DirectorySeparatorChar}def"));
Assert.Equal("", Path.GetDirectoryName(@"def"));

View File

@@ -137,11 +137,11 @@ namespace Semmle.Util
bool IsMonoInstalled();
/// <summary>
/// Combine path segments, Path.Combine().
/// Joins path segments, Path.Join().
/// </summary>
/// <param name="parts">The parts of the path.</param>
/// <returns>The combined path.</returns>
string PathCombine(params string[] parts);
string PathJoin(params string[] parts);
/// <summary>
/// Gets the full path for <paramref name="path"/>, Path.GetFullPath().
@@ -293,7 +293,7 @@ namespace Semmle.Util
}
}
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
string IBuildActions.PathJoin(params string[] parts) => Path.Join(parts);
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);

View File

@@ -43,7 +43,7 @@ namespace Semmle.Util
var parent = Directory.GetParent(path);
return parent is not null ?
Path.Combine(cache.GetCanonicalPath(parent.FullName), Path.GetFileName(path)) :
Path.Join(cache.GetCanonicalPath(parent.FullName), Path.GetFileName(path)) :
path.ToUpperInvariant();
}
}
@@ -138,12 +138,12 @@ namespace Semmle.Util
var entries = Directory.GetFileSystemEntries(parentPath, name);
return entries.Length == 1
? entries[0]
: Path.Combine(parentPath, name);
: Path.Join(parentPath, name);
}
catch // lgtm[cs/catch-of-all-exceptions]
{
// IO error or security error querying directory.
return Path.Combine(parentPath, name);
return Path.Join(parentPath, name);
}
}
}

View File

@@ -82,7 +82,7 @@ namespace Semmle.Util
{
exes = new[] { prog };
}
var candidates = paths?.Where(path => exes.Any(exe0 => File.Exists(Path.Combine(path, exe0))));
var candidates = paths?.Where(path => exes.Any(exe0 => File.Exists(Path.Join(path, exe0))));
return candidates?.FirstOrDefault();
}
@@ -179,7 +179,7 @@ namespace Semmle.Util
{
innerpath = ConvertPathToSafeRelativePath(innerpath);
nested = Path.Combine(outerpath, innerpath);
nested = Path.Join(outerpath, innerpath);
}
try
{
@@ -203,7 +203,7 @@ namespace Semmle.Util
{
var tempPath = Path.GetTempPath();
var name = Guid.NewGuid().ToString("N").ToUpper();
var tempFolder = Path.Combine(tempPath, "GitHub", name);
var tempFolder = Path.Join(tempPath, "GitHub", name);
Directory.CreateDirectory(tempFolder);
return tempFolder;
});
@@ -231,7 +231,7 @@ namespace Semmle.Util
string outputPath;
do
{
outputPath = Path.Combine(tempFolder, Path.GetRandomFileName() + extension);
outputPath = Path.Join(tempFolder, Path.GetRandomFileName() + extension);
}
while (File.Exists(outputPath));

View File

@@ -121,6 +121,13 @@ private module Cached {
result = getAChildExpr(parent)
or
result = parent.getAChildStmt()
or
result =
any(TypeMention tm |
tm.getTarget() = parent
or
tm.getParent+().getTarget() = parent
)
}
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {

View File

@@ -6,6 +6,7 @@ import Generics
import Location
import Namespace
import Property
import semmle.code.csharp.controlflow.ControlFlowElement
private import Conversion
private import semmle.code.csharp.metrics.Coupling
private import TypeRef
@@ -1286,7 +1287,7 @@ class TupleType extends ValueType, @tuple_type {
* A type mention, that is, any mention of a type in a source code file.
* For example, `int` is mentioned in `int M() { return 1; }`.
*/
class TypeMention extends @type_mention {
class TypeMention extends ControlFlowElement, @type_mention {
Type type;
@type_mention_parent parent;
@@ -1319,13 +1320,13 @@ class TypeMention extends @type_mention {
* }
* ```
*/
TypeMention getParent() { result = parent }
override TypeMention getParent() { result = parent }
/** Gets a textual representation of this type mention. */
string toString() { result = type.toString() }
override string toString() { result = type.toString() }
/** Gets the location of this type mention. */
Location getLocation() { type_mention_location(this, result) }
override Location getALocation() { type_mention_location(this, result) }
}
/**

View File

@@ -20,7 +20,7 @@ class ControlFlowElementOrCallable extends ExprOrStmtParent, TControlFlowElement
*/
class ControlFlowElement extends ControlFlowElementOrCallable, @control_flow_element {
/** Gets the enclosing callable of this element, if any. */
Callable getEnclosingCallable() { none() }
Callable getEnclosingCallable() { enclosingCallable(this, result) }
/** Gets the assembly that this element was compiled into. */
Assembly getAssembly() {

View File

@@ -145,6 +145,8 @@ module Ast implements AstSig<Location> {
final private class ParameterFinal = CS::Parameter;
class Parameter extends ParameterFinal {
AstNode getPattern() { result = this }
Expr getDefaultValue() {
// Avoid combinatorial explosions for callables with multiple bodies
result = unique( | | super.getDefaultValue())

View File

@@ -219,7 +219,7 @@ overlayChangedFiles(
/** ELEMENTS **/
@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
| @using_directive | @type_parameter_constraints | @externalDataElement
| @using_directive | @type_parameter_constraints | @type_mention | @externalDataElement
| @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
@declaration = @callable | @generic | @assignable | @namespace;
@@ -1369,7 +1369,7 @@ compiler_generated(unique int id: @element ref);
/** CONTROL/DATA FLOW **/
@control_flow_element = @stmt | @expr | @parameter;
@control_flow_element = @stmt | @expr | @parameter | @type_mention;
/* XML Files */

View File

@@ -101,6 +101,7 @@ csharp6.cs:
# 32| 0: [IntLiteral] 2
# 32| 0: [IntLiteral] 1
# 34| 1: [SpecificCatchClause] catch (...) {...}
# 34| 0: [TypeMention] IndexOutOfRangeException
# 35| 1: [BlockStmt] {...}
# 34| 2: [EQExpr] ... == ...
# 34| 0: [PropertyCall] access to property Value

View File

@@ -194,3 +194,16 @@ class C3<T> : C2<C4<T>> { }
class C4<T> : C2<C3<T>> { }
class C5 : C4<C5> { }
class CatchTypeMentions
{
void F()
{
try
{
}
catch (Exception)
{
}
}
}

View File

@@ -100,3 +100,5 @@
| Program.cs:194:21:194:21 | T |
| Program.cs:196:12:196:17 | C4<C5> |
| Program.cs:196:15:196:16 | C5 |
| Program.cs:200:5:200:8 | Void |
| Program.cs:205:16:205:24 | Exception |

View File

@@ -21,7 +21,7 @@
Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [7]_",``.java``
Kotlin,"Kotlin 1.8.0 to 2.4.0\ *x*","kotlinc",``.kt``
Kotlin,"Kotlin 1.8.0 to 2.3.2\ *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]_"
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``"

View File

@@ -123,7 +123,7 @@ k8s.io/api/core,,,10,,,,,,,,,,,,,,,,,,,,,,,10,
k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,,,,,,,47,
k8s.io/klog,90,,,,,,90,,,,,,,,,,,,,,,,,,,,
launchpad.net/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,,,
log,20,,3,,,,20,,,,,,,,,,,,,,,,,,,3,
log,40,,3,,,,40,,,,,,,,,,,,,,,,,,,3,
math/big,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
mime,,,14,,,,,,,,,,,,,,,,,,,,,,,14,
net,2,16,100,,,,,,1,,,,,,,,1,,,,,,,16,,100,
1 package sink source summary sink:command-injection sink:credentials-key sink:jwt sink:log-injection sink:nosql-injection sink:path-injection sink:regex-use[0] sink:regex-use[1] sink:regex-use[c] sink:request-forgery sink:request-forgery[TCP Addr + Port] sink:sql-injection sink:url-redirection sink:url-redirection[0] sink:url-redirection[receiver] sink:xpath-injection source:commandargs source:database source:environment source:file source:remote source:stdin summary:taint summary:value
123 k8s.io/apimachinery/pkg/runtime 47 47
124 k8s.io/klog 90 90
125 launchpad.net/xmlpath 2 2
126 log 20 40 3 20 40 3
127 math/big 1 1
128 mime 14 14
129 net 2 16 100 1 1 16 100

View File

@@ -32,7 +32,7 @@ Go framework & library support
`Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4
`SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1,
`Squirrel <https://github.com/Masterminds/squirrel>`_,"``github.com/Masterminds/squirrel*``, ``github.com/lann/squirrel*``, ``gopkg.in/Masterminds/squirrel``",81,,96
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``, ``weak``",52,612,104
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``, ``weak``",52,612,124
`XORM <https://xorm.io>`_,"``github.com/go-xorm/xorm*``, ``xorm.io/xorm*``",,,68
`XPath <https://github.com/antchfx/xpath>`_,``github.com/antchfx/xpath*``,,,4
`appleboy/gin-jwt <https://github.com/appleboy/gin-jwt>`_,``github.com/appleboy/gin-jwt*``,,,1
@@ -74,5 +74,5 @@ Go framework & library support
`xpathparser <https://github.com/santhosh-tekuri/xpathparser>`_,``github.com/santhosh-tekuri/xpathparser*``,,,2
`yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9,
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,33
Totals,,688,1072,1557
Totals,,688,1072,1577

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.

View File

@@ -0,0 +1,8 @@
---
category: minorAnalysis
---
* Added models for the `log/slog` package (Go 1.21+). Its logging functions and
`*slog.Logger` methods (`Debug`/`Info`/`Warn`/`Error`, their `Context`
variants, and `Log`/`LogAttrs`) are now recognized as logging sinks, so the
`go/log-injection` and `go/clear-text-logging` queries cover code that logs
through `slog`.

View File

@@ -0,0 +1,29 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
# Package-level convenience functions (msg string, args ...any).
- ["log/slog", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"]
# Context variants (ctx, msg string, args ...any).
- ["log/slog", "", False, "DebugContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "", False, "InfoContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "", False, "WarnContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "", False, "ErrorContext", "", "", "Argument[1..2]", "log-injection", "manual"]
# Log/LogAttrs (ctx, level, msg string, args/attrs ...).
- ["log/slog", "", False, "Log", "", "", "Argument[2..3]", "log-injection", "manual"]
- ["log/slog", "", False, "LogAttrs", "", "", "Argument[2..3]", "log-injection", "manual"]
# Methods on *slog.Logger.
- ["log/slog", "Logger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "DebugContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "InfoContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "WarnContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "ErrorContext", "", "", "Argument[1..2]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "Log", "", "", "Argument[2..3]", "log-injection", "manual"]
- ["log/slog", "Logger", True, "LogAttrs", "", "", "Argument[2..3]", "log-injection", "manual"]

View File

@@ -10,6 +10,7 @@ dependencies:
codeql/controlflow: ${workspace}
codeql/dataflow: ${workspace}
codeql/mad: ${workspace}
codeql/ssa: ${workspace}
codeql/threat-models: ${workspace}
codeql/tutorial: ${workspace}
codeql/util: ${workspace}

View File

@@ -1049,17 +1049,29 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
*/
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
/** Gets the `i`th result of this function type (0-based). */
/**
* Gets the `i`th result declaration of this function type (0-based).
*
* Note: `x, y int` is a single `ResultVariableDecl`.
*/
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
/** Gets a result of this function type. */
/**
* Gets a result declaration of this function type.
*
* Note: `x, y int` is a single `ResultVariableDecl`.
*/
ResultVariableDecl getAResultDecl() { result = this.getResultDecl(_) }
/** Gets the number of results of this function type. */
int getNumResult() { result = count(this.getAResultDecl()) }
/** Gets the number of result parameters of this function type. */
int getNumResult() { result = count(this.getAResultDecl().getANameExpr()) }
/** Gets the result of this function type, if there is only one. */
ResultVariableDecl getResultDecl() { this.getNumResult() = 1 and result = this.getAResultDecl() }
/**
* DEPRECATED: Use `getResultDecl(int i)` instead.
*/
deprecated ResultVariableDecl getResultDecl() {
this.getNumResult() = 1 and result = this.getAResultDecl()
}
override string toString() { result = "function type" }

View File

@@ -42,11 +42,11 @@ private module Input implements BB::InputSig<Location> {
predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
}
private module BbImpl = BB::Make<Location, Input>;
module Cfg = BB::Make<Location, Input>;
class BasicBlock = BbImpl::BasicBlock;
class BasicBlock = Cfg::BasicBlock;
class EntryBasicBlock = BbImpl::EntryBasicBlock;
class EntryBasicBlock = Cfg::EntryBasicBlock;
cached
private predicate reachableBB(BasicBlock bb) {

View File

@@ -63,10 +63,7 @@ private predicate unresolvedIdentifier(Ident id, string name) {
/**
* An SSA variable.
*/
class SsaVariable extends TSsaDefinition {
/** Gets the source variable corresponding to this SSA variable. */
SsaSourceVariable getSourceVariable() { result = this.(SsaDefinition).getSourceVariable() }
class SsaVariable extends Definition {
/** Gets the (unique) definition of this SSA variable. */
SsaDefinition getDefinition() { result = this }
@@ -74,22 +71,17 @@ class SsaVariable extends TSsaDefinition {
Type getType() { result = this.getSourceVariable().getType() }
/** Gets a use in basic block `bb` that refers to this SSA variable. */
IR::Instruction getAUseIn(ReachableBasicBlock bb) {
IR::Instruction getAUseIn(BasicBlock bb) {
exists(int i, SsaSourceVariable v | v = this.getSourceVariable() |
result = bb.getNode(i) and
this = getDefinition(bb, i, v)
ssaDefReachesRead(v, this, bb, i) and
useAt(bb, i, v)
)
}
/** Gets a use that refers to this SSA variable. */
IR::Instruction getAUse() { result = this.getAUseIn(_) }
/** Gets a textual representation of this element. */
string toString() { result = this.getDefinition().prettyPrintRef() }
/** Gets the location of this SSA variable. */
Location getLocation() { result = this.getDefinition().getLocation() }
/**
* DEPRECATED: Use `getLocation()` instead.
*
@@ -109,50 +101,20 @@ class SsaVariable extends TSsaDefinition {
/**
* An SSA definition.
*/
class SsaDefinition extends TSsaDefinition {
class SsaDefinition extends Definition {
/** Gets the SSA variable defined by this definition. */
SsaVariable getVariable() { result = this }
/** Gets the source variable defined by this definition. */
abstract SsaSourceVariable getSourceVariable();
/**
* Gets the basic block to which this definition belongs.
*/
abstract ReachableBasicBlock getBasicBlock();
/**
* INTERNAL: Use `getBasicBlock()` and `getSourceVariable()` instead.
*
* Holds if this is a definition of source variable `v` at index `idx` in basic block `bb`.
*
* Phi nodes are considered to be at index `-1`, all other definitions at the index of
* the control flow node they correspond to.
*/
abstract predicate definesAt(ReachableBasicBlock bb, int idx, SsaSourceVariable v);
/**
* INTERNAL: Use `toString()` instead.
*
* Gets a pretty-printed representation of this SSA definition.
*/
abstract string prettyPrintDef();
/**
* INTERNAL: Do not use.
*
* Gets a pretty-printed representation of a reference to this SSA definition.
*/
abstract string prettyPrintRef();
/** Gets the innermost function or file to which this SSA definition belongs. */
ControlFlow::Root getRoot() { result = this.getBasicBlock().getScope() }
/** Gets a textual representation of this element. */
string toString() { result = this.prettyPrintDef() }
/** Gets the source location for this element. */
abstract Location getLocation();
/**
* INTERNAL: Do not use.
*
* Gets a short string identifying the kind of this SSA definition,
* used in reference formatting (e.g., `"def"`, `"capture"`, `"phi"`).
*/
string getKind() { none() }
/**
* DEPRECATED: Use `getLocation()` instead.
@@ -180,32 +142,23 @@ class SsaDefinition extends TSsaDefinition {
/**
* An SSA definition that corresponds to an explicit assignment or other variable definition.
*/
class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
class SsaExplicitDefinition extends SsaDefinition, WriteDefinition {
SsaExplicitDefinition() {
exists(BasicBlock bb, int i, SsaSourceVariable v |
this.definesAt(v, bb, i) and
defAt(bb, i, v)
)
}
/** Gets the instruction where the definition happens. */
IR::Instruction getInstruction() {
exists(BasicBlock bb, int i | this = TExplicitDef(bb, i, _) | result = bb.getNode(i))
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i))
}
/** Gets the right-hand side of the definition. */
IR::Instruction getRhs() { this.getInstruction().writes(_, result) }
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
this = TExplicitDef(bb, i, v)
}
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, result) }
override string prettyPrintRef() {
exists(Location loc | loc = this.getLocation() |
result = "def@" + loc.getStartLine() + ":" + loc.getStartColumn()
)
}
override string prettyPrintDef() { result = "definition of " + this.getSourceVariable() }
override Location getLocation() { result = this.getInstruction().getLocation() }
override string getKind() { result = "def" }
}
/** Provides a helper predicate for working with explicit SSA definitions. */
@@ -219,22 +172,7 @@ module SsaExplicitDefinition {
/**
* An SSA definition that does not correspond to an explicit variable definition.
*/
abstract class SsaImplicitDefinition extends SsaDefinition {
/**
* INTERNAL: Do not use.
*
* Gets the definition kind to include in `prettyPrintRef`.
*/
abstract string getKind();
override string prettyPrintRef() {
exists(Location loc | loc = this.getLocation() |
result = this.getKind() + "@" + loc.getStartLine() + ":" + loc.getStartColumn()
)
}
override Location getLocation() { result = this.getBasicBlock().getLocation() }
}
abstract class SsaImplicitDefinition extends SsaDefinition { }
/**
* An SSA definition representing the capturing of an SSA-convertible variable
@@ -243,24 +181,8 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
* Capturing definitions appear at the beginning of such functions, as well as
* at any function call that may affect the value of the variable.
*/
class SsaVariableCapture extends SsaImplicitDefinition, TCapture {
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
this = TCapture(bb, i, v)
}
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
override SsaSourceVariable getSourceVariable() { this.definesAt(_, _, result) }
class SsaVariableCapture extends SsaImplicitDefinition, UncertainWriteDefinition {
override string getKind() { result = "capture" }
override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }
override Location getLocation() {
exists(ReachableBasicBlock bb, int i | this.definesAt(bb, i, _) |
result = bb.getNode(i).getLocation()
)
}
}
/**
@@ -272,12 +194,6 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
* Gets an input of this pseudo-definition.
*/
abstract SsaVariable getAnInput();
/**
* Gets a textual representation of the inputs of this pseudo-definition
* in lexicographical order.
*/
string ppInputs() { result = concat(this.getAnInput().getDefinition().prettyPrintRef(), ", ") }
}
/**
@@ -285,26 +201,10 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
* in the flow graph where otherwise two or more definitions for the variable
* would be visible.
*/
class SsaPhiNode extends SsaPseudoDefinition, TPhi {
override SsaVariable getAnInput() {
result = getDefReachingEndOf(this.getBasicBlock().getAPredecessor(_), this.getSourceVariable())
}
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
bb = this.getBasicBlock() and v = this.getSourceVariable() and i = -1
}
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
override SsaSourceVariable getSourceVariable() { this = TPhi(_, result) }
class SsaPhiNode extends SsaPseudoDefinition, PhiNode {
override SsaVariable getAnInput() { phiHasInputFromBlock(this, result, _) }
override string getKind() { result = "phi" }
override string prettyPrintDef() {
result = this.getSourceVariable() + " = phi(" + this.ppInputs() + ")"
}
override Location getLocation() { result = this.getBasicBlock().getLocation() }
}
/**

View File

@@ -7,76 +7,25 @@ overlay[local]
module;
import go
private import codeql.ssa.Ssa as SsaImplCommon
private import semmle.go.controlflow.BasicBlocks as BasicBlocks
private class BasicBlock = BasicBlocks::BasicBlock;
cached
private module Internal {
/** Holds if the `i`th node of `bb` defines `v`. */
cached
predicate defAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
predicate defAt(BasicBlock bb, int i, SsaSourceVariable v) {
bb.getNode(i).(IR::Instruction).writes(v, _)
}
/** Holds if the `i`th node of `bb` reads `v`. */
cached
predicate useAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
predicate useAt(BasicBlock bb, int i, SsaSourceVariable v) {
bb.getNode(i).(IR::Instruction).reads(v)
}
/**
* A data type representing SSA definitions.
*
* We distinguish three kinds of SSA definitions:
*
* 1. Variable definitions, including declarations, assignments and increments/decrements.
* 2. Pseudo-definitions for captured variables at the beginning of the capturing function
* as well as after calls.
* 3. Phi nodes.
*
* SSA definitions are only introduced where necessary. In particular,
* unreachable code has no SSA definitions associated with it, and neither
* have dead assignments (that is, assignments whose value is never read).
*/
cached
newtype TSsaDefinition =
/**
* An SSA definition that corresponds to an explicit assignment or other variable definition.
*/
TExplicitDef(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
defAt(bb, i, v) and
(liveAfterDef(bb, i, v) or v.isCaptured())
} or
/**
* An SSA definition representing the capturing of an SSA-convertible variable
* in the closure of a nested function.
*
* Capturing definitions appear at the beginning of such functions, as well as
* at any function call that may affect the value of the variable.
*/
TCapture(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
mayCapture(bb, i, v) and
liveAfterDef(bb, i, v)
} or
/**
* An SSA phi node, that is, a pseudo-definition for a variable at a point
* in the flow graph where otherwise two or more definitions for the variable
* would be visible.
*/
TPhi(ReachableJoinBlock bb, SsaSourceVariable v) {
liveAtEntry(bb, v) and
inDefDominanceFrontier(bb, v)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(ReachableJoinBlock bb, SsaSourceVariable v) {
exists(ReachableBasicBlock defbb, SsaDefinition def |
def.definesAt(defbb, _, v) and
defbb.inDominanceFrontier(bb)
)
}
/**
* Holds if `v` is a captured variable which is declared in `declFun` and read in `useFun`.
*/
@@ -87,7 +36,7 @@ private module Internal {
}
/** Holds if the `i`th node of `bb` in function `f` is an entry node. */
private predicate entryNode(FuncDef f, ReachableBasicBlock bb, int i) {
private predicate entryNode(FuncDef f, BasicBlock bb, int i) {
f = bb.getScope() and
bb.getNode(i).isEntryNode()
}
@@ -95,17 +44,17 @@ private module Internal {
/**
* Holds if the `i`th node of `bb` in function `f` is a function call.
*/
private predicate callNode(FuncDef f, ReachableBasicBlock bb, int i) {
private predicate callNode(FuncDef f, BasicBlock bb, int i) {
f = bb.getScope() and
bb.getNode(i).(IR::EvalInstruction).getExpr() instanceof CallExpr
}
/**
* Holds if the `i`th node of basic block `bb` may induce a pseudo-definition for
* modeling updates to captured variable `v`. Whether the definition is actually
* introduced depends on whether `v` is live at this point in the program.
* modeling updates to captured variable `v`.
*/
private predicate mayCapture(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
cached
predicate mayUpdateCapturedVariable(BasicBlock bb, int i, SsaSourceVariable v) {
exists(FuncDef capturingContainer, FuncDef declContainer |
// capture initial value of variable declared in enclosing scope
readsCapturedVar(capturingContainer, v, declContainer) and
@@ -119,347 +68,134 @@ private module Internal {
)
}
/** A classification of variable references into reads and writes. */
private newtype RefKind =
ReadRef() or
WriteRef()
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`, either a read
* (when `tp` is `ReadRef()`) or a direct or indirect write (when `tp` is `WriteRef()`).
*/
private predicate ref(ReachableBasicBlock bb, int i, SsaSourceVariable v, RefKind tp) {
useAt(bb, i, v) and tp = ReadRef()
or
(mayCapture(bb, i, v) or defAt(bb, i, v)) and
tp = WriteRef()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic block `bb`,
* which has the given reference kind `tp`.
*/
private int refRank(ReachableBasicBlock bb, int i, SsaSourceVariable v, RefKind tp) {
i = rank[result](int j | ref(bb, j, v, _)) and
ref(bb, i, v, tp)
}
/**
* Gets the maximum rank among all references to `v` in basic block `bb`.
*/
private int maxRefRank(ReachableBasicBlock bb, SsaSourceVariable v) {
result = max(refRank(bb, _, v, _))
}
/**
* Holds if variable `v` is live after the `i`th node of basic block `bb`, where
* `i` is the index of a node that may assign or capture `v`.
*
* For the purposes of this predicate, function calls are considered as writes of captured variables.
*/
private predicate liveAfterDef(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
exists(int r | r = refRank(bb, i, v, WriteRef()) |
// the next reference to `v` inside `bb` is a read
r + 1 = refRank(bb, _, v, ReadRef())
or
// this is the last reference to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
r = maxRefRank(bb, v) and
liveAtSuccEntry(bb, v)
)
}
/**
* Holds if variable `v` is live at the beginning of basic block `bb`.
*
* For the purposes of this predicate, function calls are considered as writes of captured variables.
*/
private predicate liveAtEntry(ReachableBasicBlock bb, SsaSourceVariable v) {
// the first reference to `v` inside `bb` is a read
refRank(bb, _, v, ReadRef()) = 1
or
// there is no reference to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(refRank(bb, _, v, _)) and
liveAtSuccEntry(bb, v)
}
/**
* Holds if `v` is live at the beginning of any successor of basic block `bb`.
*/
private predicate liveAtSuccEntry(ReachableBasicBlock bb, SsaSourceVariable v) {
liveAtEntry(bb.getASuccessor(_), v)
}
/**
* Holds if `v` is assigned outside its declaring function.
*/
private predicate assignedThroughClosure(SsaSourceVariable v) {
cached
predicate assignedThroughClosure(SsaSourceVariable v) {
any(IR::Instruction def | def.writes(v, _)).getRoot() != v.getDeclaringFunction()
}
/**
* Holds if the `i`th node of `bb` is a use or an SSA definition of variable `v`, with
* `k` indicating whether it is the former or the latter.
*
* Note this includes phi nodes, whereas `ref` above only includes explicit writes and captures.
*/
private predicate ssaRef(ReachableBasicBlock bb, int i, SsaSourceVariable v, RefKind k) {
useAt(bb, i, v) and k = ReadRef()
or
any(SsaDefinition def).definesAt(bb, i, v) and k = WriteRef()
}
/** SSA input. */
cached
module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
class SourceVariable = SsaSourceVariable;
/**
* Gets the (1-based) rank of the `i`th node of `bb` among all SSA definitions
* and uses of `v` in `bb`, with `k` indicating whether it is a definition or a use.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), uses `v` at node 2 and defines it at node 5, we have:
*
* ```
* ssaRefRank(bb, -1, v, WriteRef()) = 1 // phi node
* ssaRefRank(bb, 2, v, ReadRef()) = 2 // use at node 2
* ssaRefRank(bb, 5, v, WriteRef()) = 3 // definition at node 5
* ```
*/
private int ssaRefRank(ReachableBasicBlock bb, int i, SsaSourceVariable v, RefKind k) {
i = rank[result](int j | ssaRef(bb, j, v, _)) and
ssaRef(bb, i, v, k)
}
/**
* Holds if the `i`th node of basic block `bb` is a (potential) write to source
* variable `v`. The Boolean `certain` indicates whether the write is certain.
*
* Certain writes are explicit definitions; uncertain writes are captures.
*/
cached
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
defAt(bb, i, v) and certain = true
or
mayUpdateCapturedVariable(bb, i, v) and certain = false
}
/**
* Gets the minimum rank of a read in `bb` such that all references to `v` between that
* read and the read at index `i` are reads (and not writes).
*/
private int rewindReads(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
exists(int r | r = ssaRefRank(bb, i, v, ReadRef()) |
exists(int j, RefKind k | r - 1 = ssaRefRank(bb, j, v, k) |
k = ReadRef() and result = rewindReads(bb, j, v)
/**
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
*
* We add a synthetic uncertain read at the exit node of every function
* that references a captured variable `v`. This ensures that definitions
* of captured variables are included in the SSA graph even when the
* variable is not locally read in that function scope (but may be read
* by another function sharing the same closure).
*/
cached
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
useAt(bb, i, v) and certain = true
or
v.isCaptured() and
exists(FuncDef f |
f = bb.getScope() and
bb.getLastNode().isExitNode() and
i = bb.length() - 1 and
certain = false
|
// The declaring function: captures may be read after calls to closures
f = v.getDeclaringFunction()
or
k = WriteRef() and result = r
)
or
r = 1 and result = r
)
}
/**
* Gets the SSA definition of `v` in `bb` that reaches the read of `v` at node `i`, if any.
*/
private SsaDefinition getLocalDefinition(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
exists(int r | r = rewindReads(bb, i, v) |
exists(int j | result.definesAt(bb, j, v) and ssaRefRank(bb, j, v, _) = r - 1)
)
}
/**
* Gets an SSA definition of `v` that reaches the end of the immediate dominator of `bb`.
*/
pragma[noinline]
private SsaDefinition getDefReachingEndOfImmediateDominator(
ReachableBasicBlock bb, SsaSourceVariable v
) {
result = getDefReachingEndOf(bb.getImmediateDominator(), v)
}
/**
* Gets an SSA definition of `v` that reaches the end of basic block `bb`.
*/
cached
SsaDefinition getDefReachingEndOf(ReachableBasicBlock bb, SsaSourceVariable v) {
exists(int lastRef | lastRef = max(int i | ssaRef(bb, i, v, _)) |
result = getLocalDefinition(bb, lastRef, v)
or
result.definesAt(bb, lastRef, v) and
liveAtSuccEntry(bb, v)
)
or
// In SSA form, the (unique) reaching definition of a use is the closest
// definition that dominates the use. If two definitions dominate a node
// then one must dominate the other, so we can find the reaching definition
// by following the idominance relation backwards.
result = getDefReachingEndOfImmediateDominator(bb, v) and
not exists(SsaDefinition ssa | ssa.definesAt(bb, _, v)) and
liveAtSuccEntry(bb, v)
}
/**
* Gets the unique SSA definition of `v` whose value reaches the `i`th node of `bb`,
* which is a use of `v`.
*/
cached
SsaDefinition getDefinition(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
result = getLocalDefinition(bb, i, v)
or
rewindReads(bb, i, v) = 1 and result = getDefReachingEndOf(bb.getImmediateDominator(), v)
}
private module AdjacentUsesImpl {
/** Holds if `v` is defined or used in `b`. */
private predicate varOccursInBlock(SsaSourceVariable v, ReachableBasicBlock b) {
ssaRef(b, _, v, _)
}
/** Holds if `v` occurs in `b` or one of `b`'s transitive successors. */
private predicate blockPrecedesVar(SsaSourceVariable v, ReachableBasicBlock b) {
varOccursInBlock(v, b)
or
exists(getDefReachingEndOf(b, v))
}
/**
* Holds if `v` occurs in `b1` and `b2` is one of `b1`'s successors.
*
* Factored out of `varBlockReaches` to force join order compared to the larger
* set `blockPrecedesVar(v, b2)`.
*/
pragma[noinline]
private predicate varBlockReachesBaseCand(
SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2
) {
varOccursInBlock(v, b1) and
b2 = b1.getASuccessor(_)
}
/**
* Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and
* in `b2` or one of its transitive successors but not in any block on the path
* between `b1` and `b2`. Unlike `varBlockReaches` this may include blocks `b2`
* where `v` is dead.
*
* Factored out of `varBlockReaches` to force join order compared to the larger
* set `blockPrecedesVar(v, b2)`.
*/
pragma[noinline]
private predicate varBlockReachesRecCand(
SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock mid, ReachableBasicBlock b2
) {
varBlockReaches(v, b1, mid) and
not varOccursInBlock(v, mid) and
b2 = mid.getASuccessor(_)
}
/**
* Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and
* in `b2` or one of its transitive successors but not in any block on the path
* between `b1` and `b2`.
*/
private predicate varBlockReaches(
SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2
) {
varBlockReachesBaseCand(v, b1, b2) and
blockPrecedesVar(v, b2)
or
varBlockReachesRecCand(v, b1, _, b2) and
blockPrecedesVar(v, b2)
}
/**
* Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and
* `b2` but not in any block on the path between `b1` and `b2`.
*/
private predicate varBlockStep(
SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2
) {
varBlockReaches(v, b1, b2) and
varOccursInBlock(v, b2)
}
/**
* Gets the maximum rank among all SSA references to `v` in basic block `bb`.
*/
private int maxSsaRefRank(ReachableBasicBlock bb, SsaSourceVariable v) {
result = max(ssaRefRank(bb, _, v, _))
}
/**
* Holds if `v` occurs at index `i1` in `b1` and at index `i2` in `b2` and
* there is a path between them without any occurrence of `v`.
*/
pragma[nomagic]
predicate adjacentVarRefs(
SsaSourceVariable v, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, int i2
) {
exists(int rankix |
b1 = b2 and
ssaRefRank(b1, i1, v, _) = rankix and
ssaRefRank(b2, i2, v, _) = rankix + 1
)
or
maxSsaRefRank(b1, v) = ssaRefRank(b1, i1, v, _) and
varBlockStep(v, b1, b2) and
ssaRefRank(b2, i2, v, _) = 1
}
predicate variableUse(SsaSourceVariable v, IR::Instruction use, ReachableBasicBlock bb, int i) {
bb.getNode(i) = use and
exists(SsaVariable sv |
sv.getSourceVariable() = v and
use = sv.getAUse()
// Any function that writes `v`: the write may be observed by the
// declaring function or another closure sharing the same variable
any(IR::Instruction def | def.writes(v, _)).getRoot() = f
)
}
}
private import AdjacentUsesImpl
/**
* Holds if the value defined at `def` can reach `use` without passing through
* any other uses, but possibly through phi nodes.
*/
cached
predicate firstUse(SsaDefinition def, IR::Instruction use) {
exists(SsaSourceVariable v, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, int i2 |
adjacentVarRefs(v, b1, i1, b2, i2) and
def.definesAt(b1, i1, v) and
variableUse(v, use, b2, i2)
)
or
exists(
SsaSourceVariable v, SsaPhiNode redef, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2,
int i2
|
adjacentVarRefs(v, b1, i1, b2, i2) and
def.definesAt(b1, i1, v) and
redef.definesAt(b2, i2, v) and
firstUse(redef, use)
)
}
/**
* Holds if `use1` and `use2` form an adjacent use-use-pair of the same SSA
* variable, that is, the value read in `use1` can reach `use2` without passing
* through any other use or any SSA definition of the variable.
*/
cached
predicate adjacentUseUseSameVar(IR::Instruction use1, IR::Instruction use2) {
exists(SsaSourceVariable v, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, int i2 |
adjacentVarRefs(v, b1, i1, b2, i2) and
variableUse(v, use1, b1, i1) and
variableUse(v, use2, b2, i2)
)
}
/**
* Holds if `use1` and `use2` form an adjacent use-use-pair of the same
* `SsaSourceVariable`, that is, the value read in `use1` can reach `use2`
* without passing through any other use or any SSA definition of the variable
* except for phi nodes and uncertain implicit updates.
*/
cached
predicate adjacentUseUse(IR::Instruction use1, IR::Instruction use2) {
adjacentUseUseSameVar(use1, use2)
or
exists(
SsaSourceVariable v, SsaPhiNode def, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2,
int i2
|
adjacentVarRefs(v, b1, i1, b2, i2) and
variableUse(v, use1, b1, i1) and
def.definesAt(b2, i2, v) and
firstUse(def, use2)
)
}
}
import Internal
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
final class Definition = Impl::Definition;
final class WriteDefinition = Impl::WriteDefinition;
final class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
final class PhiNode = Impl::PhiNode;
module Consistency = Impl::Consistency;
/**
* NB: This predicate should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`.
*/
cached
predicate ssaDefReachesRead(SsaSourceVariable v, Definition def, BasicBlock bb, int i) {
Impl::ssaDefReachesRead(v, def, bb, i)
}
/**
* NB: This predicate should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic block `bb`.
*/
cached
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SsaSourceVariable v) {
Impl::ssaDefReachesEndOfBlock(bb, def, v)
}
/**
* NB: This predicate should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
cached
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
Impl::phiHasInputFromBlock(phi, inp, bb)
}
/**
* NB: This predicate should be cached.
*
* Holds if `def` reaches the first use `use` without going through any other use,
* but possibly through phi nodes.
*/
cached
predicate firstUse(Definition def, IR::Instruction use) {
exists(BasicBlock bb, int i |
Impl::firstUse(def, bb, i, _) and
use = bb.getNode(i)
)
}
/**
* NB: This predicate should be cached.
*
* Holds if `use1` and `use2` form an adjacent use-use-pair of the same SSA
* variable, that is, the value read in `use1` can reach `use2` without passing
* through any other use or any SSA definition of the variable except for phi nodes
* and uncertain implicit updates.
*/
cached
predicate adjacentUseUse(IR::Instruction use1, IR::Instruction use2) {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
Impl::adjacentUseUse(bb1, i1, bb2, i2, _, _) and
use1 = bb1.getNode(i1) and
use2 = bb2.getNode(i2)
)
}

View File

@@ -923,15 +923,20 @@ module Public {
/**
* A node whose value is returned as a result from a function.
*
* This can either be a node corresponding to an expression in a return statement,
* or a node representing the current value of a named result variable at the exit
* of the function.
* If the function declares named result variables, this is a node representing
* the current value of one of those variables at function exit. Otherwise, this
* is a node corresponding to an expression in a return statement.
*/
class ResultNode extends InstructionNode {
int i;
ResultNode() {
exists(FuncDef fd |
// If the function has named result variables, then the
// `IR::ReadResultInstruction` nodes at the end of the function are
// the correct result nodes. Otherwise, the returned expressions are
// the result nodes.
not exists(fd.getAResultVar()) and
exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i))
or
insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i))

View File

@@ -55,7 +55,7 @@ class SyncFileFun extends Method {
/**
* Holds if a `call` to a function is "unhandled". That is, it is either
* deferred or its result is not assigned to anything.
* deferred or used as an expression statement, so that its result is discarded.
*
* TODO: maybe we should check that something is actually done with the result
*/
@@ -77,7 +77,6 @@ predicate isWritableFileHandle(DataFlow::Node source, DataFlow::CallNode call) {
// get the flags expression used for opening the file
call.getArgument(1) = flags and
// extract individual flags from the argument
// flag = flag.getAChild*() and
flag = getConstants(flags.asExpr()) and
// check for one which signals that the handle will be writable
// note that we are underestimating here, since the flags may be
@@ -87,27 +86,18 @@ predicate isWritableFileHandle(DataFlow::Node source, DataFlow::CallNode call) {
}
/**
* Holds if `os.File.Close` is called on `sink`.
* Holds if `postDominator` post-dominates `node` in the control-flow graph. That is,
* every path from `node` to the exit of the enclosing function passes through
* `postDominator`.
*/
predicate isCloseSink(DataFlow::Node sink, DataFlow::CallNode closeCall) {
// find calls to the os.File.Close function
closeCall = any(CloseFileFun f).getACall() and
// that are unhandled
unhandledCall(closeCall) and
// where the function is called on the sink
closeCall.getReceiver() = sink and
// and check that it is not dominated by a call to `os.File.Sync`.
// TODO: fix this logic when `closeCall` is in a defer statement.
not exists(IR::Instruction syncInstr, DataFlow::Node syncReceiver, DataFlow::CallNode syncCall |
// match the instruction corresponding to an `os.File.Sync` call with the predecessor
syncCall.asInstruction() = syncInstr and
// check that the call to `os.File.Sync` is handled
isHandledSync(syncReceiver, syncCall) and
// find a predecessor to `closeCall` in the control flow graph which dominates the call to
// `os.File.Close`
syncInstr.dominatesNode(closeCall.asInstruction()) and
// check that `os.File.Sync` is called on the same object as `os.File.Close`
exists(DataFlow::SsaNode ssa | ssa.getAUse() = sink and ssa.getAUse() = syncReceiver)
pragma[inline]
predicate postDominatesNode(ControlFlow::Node postDominator, ControlFlow::Node node) {
exists(ReachableBasicBlock pdbb, ReachableBasicBlock nbb, int i, int j |
postDominator = pdbb.getNode(i) and node = nbb.getNode(j)
|
pdbb.strictlyPostDominates(nbb)
or
pdbb = nbb and i >= j
)
}
@@ -127,7 +117,39 @@ predicate isHandledSync(DataFlow::Node sink, DataFlow::CallNode syncCall) {
module UnhandledFileCloseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isWritableFileHandle(source, _) }
predicate isSink(DataFlow::Node sink) { isCloseSink(sink, _) }
predicate isSink(DataFlow::Node sink) {
exists(DataFlow::CallNode closeCall |
// `closeCall` is an unhandled call to `os.File.Close` on `sink`
closeCall = any(CloseFileFun f).getACall() and
unhandledCall(closeCall) and
closeCall.getReceiver() = sink
|
// `closeCall` is not guaranteed to be preceded during
// execution by a handled call to `os.File.Sync` on the same file handle.
not exists(DataFlow::Node syncReceiver, DataFlow::CallNode syncCall |
// check that the call to `os.File.Sync` is handled
isHandledSync(syncReceiver, syncCall) and
// check that `os.File.Sync` is called on the same object as `os.File.Close`
exists(DataFlow::SsaNode ssa | ssa.getAUse() = sink and ssa.getAUse() = syncReceiver)
|
if exists(DeferStmt defer | defer.getCall() = closeCall.asExpr())
then
// When the call to `os.File.Close` is deferred it runs when the enclosing function
// returns, but the receiver of the deferred call is evaluated where the `defer`
// statement appears. It is therefore enough for the handled call to `os.File.Sync`
// to post-dominate that point, since that guarantees `os.File.Sync` runs before the
// deferred `os.File.Close` on every path on which the `os.File.Close` is registered.
// We cannot reuse the domination check below because the control-flow graph splices
// the deferred call in at the function exit, where it may be reachable along paths
// that do not pass through the call to `os.File.Sync`.
postDominatesNode(syncCall.asInstruction(), sink.asInstruction())
else
// Otherwise the call to `os.File.Close` is executed where it appears, so we require
// the handled call to `os.File.Sync` to dominate it.
syncCall.asInstruction().dominatesNode(closeCall.asInstruction())
)
)
}
predicate observeDiffInformedIncrementalMode() { any() }
@@ -148,14 +170,12 @@ import UnhandledFileCloseFlow::PathGraph
from
UnhandledFileCloseFlow::PathNode source, DataFlow::CallNode openCall,
UnhandledFileCloseFlow::PathNode sink, DataFlow::CallNode closeCall
UnhandledFileCloseFlow::PathNode sink
where
// find data flow from an `os.OpenFile` call to an `os.File.Close` call
// where the handle is writable
UnhandledFileCloseFlow::flowPath(source, sink) and
isWritableFileHandle(source.getNode(), openCall) and
// get the `CallNode` corresponding to the sink
isCloseSink(sink.getNode(), closeCall)
isWritableFileHandle(source.getNode(), openCall)
select sink, source, sink,
"File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly.",
openCall, openCall.toString()

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `go/unhandled-writable-file-close` ("Writable file handle closed without error handling") now produces fewer false positives. A deferred call to `Close` that is preceded on every execution path by a handled call to `Sync` on the same file handle is no longer flagged.

View File

@@ -2,7 +2,7 @@
| file://:0:0:0:0 | [summary param] -1 in Clone |
| file://:0:0:0:0 | [summary param] -1 in Write |
| file://:0:0:0:0 | [summary param] -1 in WriteProxy |
| main.go:18:12:18:14 | SSA def(req) |
| main.go:18:12:18:14 | argument corresponding to req |
| main.go:18:12:18:14 | definition of req |
| main.go:20:5:20:7 | req |
| main.go:20:5:20:7 | req [postupdate] |

View File

@@ -47,27 +47,27 @@
| test.go:621:25:621:31 | tarRead | test.go:93:5:93:16 | selection of Body | test.go:621:25:621:31 | tarRead | This decompression is $@. | test.go:93:5:93:16 | selection of Body | decompressing compressed data without managing output size |
| test.go:629:2:629:8 | tarRead | test.go:93:5:93:16 | selection of Body | test.go:629:2:629:8 | tarRead | This decompression is $@. | test.go:93:5:93:16 | selection of Body | decompressing compressed data without managing output size |
edges
| test.go:59:16:59:44 | call to FormValue | test.go:128:20:128:27 | definition of filename | provenance | Src:MaD:2 |
| test.go:60:15:60:26 | selection of Body | test.go:158:19:158:22 | definition of file | provenance | Src:MaD:1 |
| test.go:61:24:61:35 | selection of Body | test.go:169:28:169:31 | definition of file | provenance | Src:MaD:1 |
| test.go:62:13:62:24 | selection of Body | test.go:181:17:181:20 | definition of file | provenance | Src:MaD:1 |
| test.go:64:8:64:19 | selection of Body | test.go:208:12:208:15 | definition of file | provenance | Src:MaD:1 |
| test.go:66:8:66:19 | selection of Body | test.go:233:12:233:15 | definition of file | provenance | Src:MaD:1 |
| test.go:68:17:68:28 | selection of Body | test.go:258:21:258:24 | definition of file | provenance | Src:MaD:1 |
| test.go:70:13:70:24 | selection of Body | test.go:283:17:283:20 | definition of file | provenance | Src:MaD:1 |
| test.go:72:16:72:27 | selection of Body | test.go:308:20:308:23 | definition of file | provenance | Src:MaD:1 |
| test.go:74:7:74:18 | selection of Body | test.go:333:11:333:14 | definition of file | provenance | Src:MaD:1 |
| test.go:76:9:76:20 | selection of Body | test.go:358:13:358:16 | definition of file | provenance | Src:MaD:1 |
| test.go:78:18:78:29 | selection of Body | test.go:384:22:384:25 | definition of file | provenance | Src:MaD:1 |
| test.go:80:5:80:16 | selection of Body | test.go:412:9:412:12 | definition of file | provenance | Src:MaD:1 |
| test.go:82:7:82:18 | selection of Body | test.go:447:11:447:14 | definition of file | provenance | Src:MaD:1 |
| test.go:84:15:84:26 | selection of Body | test.go:440:19:440:21 | definition of src | provenance | Src:MaD:1 |
| test.go:85:16:85:27 | selection of Body | test.go:472:20:472:23 | definition of file | provenance | Src:MaD:1 |
| test.go:87:16:87:27 | selection of Body | test.go:499:20:499:23 | definition of file | provenance | Src:MaD:1 |
| test.go:89:17:89:28 | selection of Body | test.go:526:21:526:24 | definition of file | provenance | Src:MaD:1 |
| test.go:91:15:91:26 | selection of Body | test.go:555:19:555:22 | definition of file | provenance | Src:MaD:1 |
| test.go:93:5:93:16 | selection of Body | test.go:580:9:580:12 | definition of file | provenance | Src:MaD:1 |
| test.go:128:20:128:27 | definition of filename | test.go:130:33:130:40 | filename | provenance | |
| test.go:59:16:59:44 | call to FormValue | test.go:128:20:128:27 | SSA def(filename) | provenance | Src:MaD:2 |
| test.go:60:15:60:26 | selection of Body | test.go:158:19:158:22 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:61:24:61:35 | selection of Body | test.go:169:28:169:31 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:62:13:62:24 | selection of Body | test.go:181:17:181:20 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:64:8:64:19 | selection of Body | test.go:208:12:208:15 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:66:8:66:19 | selection of Body | test.go:233:12:233:15 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:68:17:68:28 | selection of Body | test.go:258:21:258:24 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:70:13:70:24 | selection of Body | test.go:283:17:283:20 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:72:16:72:27 | selection of Body | test.go:308:20:308:23 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:74:7:74:18 | selection of Body | test.go:333:11:333:14 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:76:9:76:20 | selection of Body | test.go:358:13:358:16 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:78:18:78:29 | selection of Body | test.go:384:22:384:25 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:80:5:80:16 | selection of Body | test.go:412:9:412:12 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:82:7:82:18 | selection of Body | test.go:447:11:447:14 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:84:15:84:26 | selection of Body | test.go:440:19:440:21 | SSA def(src) | provenance | Src:MaD:1 |
| test.go:85:16:85:27 | selection of Body | test.go:472:20:472:23 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:87:16:87:27 | selection of Body | test.go:499:20:499:23 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:89:17:89:28 | selection of Body | test.go:526:21:526:24 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:91:15:91:26 | selection of Body | test.go:555:19:555:22 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:93:5:93:16 | selection of Body | test.go:580:9:580:12 | SSA def(file) | provenance | Src:MaD:1 |
| test.go:128:20:128:27 | SSA def(filename) | test.go:130:33:130:40 | filename | provenance | |
| test.go:130:2:130:41 | ... := ...[0] | test.go:132:12:132:12 | f | provenance | |
| test.go:130:33:130:40 | filename | test.go:130:2:130:41 | ... := ...[0] | provenance | Config |
| test.go:130:33:130:40 | filename | test.go:143:51:143:58 | filename | provenance | |
@@ -77,7 +77,7 @@ edges
| test.go:143:51:143:58 | filename | test.go:143:2:143:59 | ... := ...[0] | provenance | Config |
| test.go:145:12:145:12 | f | test.go:145:12:145:19 | call to Open | provenance | Config |
| test.go:145:12:145:19 | call to Open | test.go:147:37:147:38 | rc | provenance | |
| test.go:158:19:158:22 | definition of file | test.go:159:25:159:28 | file | provenance | |
| test.go:158:19:158:22 | SSA def(file) | test.go:159:25:159:28 | file | provenance | |
| test.go:159:2:159:29 | ... := ...[0] | test.go:160:48:160:52 | file1 | provenance | |
| test.go:159:25:159:28 | file | test.go:159:2:159:29 | ... := ...[0] | provenance | MaD:6 |
| test.go:160:2:160:69 | ... := ...[0] | test.go:163:26:163:29 | file | provenance | |
@@ -85,7 +85,7 @@ edges
| test.go:160:48:160:52 | file1 | test.go:160:32:160:53 | call to NewReader | provenance | MaD:5 |
| test.go:163:3:163:36 | ... := ...[0] | test.go:164:36:164:51 | fileReaderCloser | provenance | |
| test.go:163:26:163:29 | file | test.go:163:3:163:36 | ... := ...[0] | provenance | MaD:4 |
| test.go:169:28:169:31 | definition of file | test.go:170:25:170:28 | file | provenance | |
| test.go:169:28:169:31 | SSA def(file) | test.go:170:25:170:28 | file | provenance | |
| test.go:170:2:170:29 | ... := ...[0] | test.go:171:57:171:61 | file2 | provenance | |
| test.go:170:25:170:28 | file | test.go:170:2:170:29 | ... := ...[0] | provenance | MaD:6 |
| test.go:171:2:171:78 | ... := ...[0] | test.go:175:26:175:29 | file | provenance | |
@@ -93,64 +93,64 @@ edges
| test.go:171:57:171:61 | file2 | test.go:171:41:171:62 | call to NewReader | provenance | MaD:5 |
| test.go:175:26:175:29 | file | test.go:175:26:175:36 | call to Open | provenance | Config |
| test.go:175:26:175:36 | call to Open | test.go:176:36:176:51 | fileReaderCloser | provenance | |
| test.go:181:17:181:20 | definition of file | test.go:184:41:184:44 | file | provenance | |
| test.go:181:17:181:20 | SSA def(file) | test.go:184:41:184:44 | file | provenance | |
| test.go:184:2:184:73 | ... := ...[0] | test.go:186:2:186:12 | bzip2Reader | provenance | |
| test.go:184:2:184:73 | ... := ...[0] | test.go:187:26:187:36 | bzip2Reader | provenance | |
| test.go:184:41:184:44 | file | test.go:184:2:184:73 | ... := ...[0] | provenance | Config |
| test.go:187:12:187:37 | call to NewReader | test.go:189:18:189:24 | tarRead | provenance | |
| test.go:187:26:187:36 | bzip2Reader | test.go:187:12:187:37 | call to NewReader | provenance | MaD:3 |
| test.go:189:18:189:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:208:12:208:15 | definition of file | test.go:211:33:211:36 | file | provenance | |
| test.go:189:18:189:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:208:12:208:15 | SSA def(file) | test.go:211:33:211:36 | file | provenance | |
| test.go:211:17:211:37 | call to NewReader | test.go:213:2:213:12 | bzip2Reader | provenance | |
| test.go:211:17:211:37 | call to NewReader | test.go:214:26:214:36 | bzip2Reader | provenance | |
| test.go:211:33:211:36 | file | test.go:211:17:211:37 | call to NewReader | provenance | Config |
| test.go:214:12:214:37 | call to NewReader | test.go:216:18:216:24 | tarRead | provenance | |
| test.go:214:26:214:36 | bzip2Reader | test.go:214:12:214:37 | call to NewReader | provenance | MaD:3 |
| test.go:216:18:216:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:233:12:233:15 | definition of file | test.go:236:33:236:36 | file | provenance | |
| test.go:216:18:216:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:233:12:233:15 | SSA def(file) | test.go:236:33:236:36 | file | provenance | |
| test.go:236:17:236:37 | call to NewReader | test.go:238:2:238:12 | flateReader | provenance | |
| test.go:236:17:236:37 | call to NewReader | test.go:239:26:239:36 | flateReader | provenance | |
| test.go:236:33:236:36 | file | test.go:236:17:236:37 | call to NewReader | provenance | Config |
| test.go:239:12:239:37 | call to NewReader | test.go:241:18:241:24 | tarRead | provenance | |
| test.go:239:26:239:36 | flateReader | test.go:239:12:239:37 | call to NewReader | provenance | MaD:3 |
| test.go:241:18:241:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:258:21:258:24 | definition of file | test.go:261:42:261:45 | file | provenance | |
| test.go:241:18:241:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:258:21:258:24 | SSA def(file) | test.go:261:42:261:45 | file | provenance | |
| test.go:261:17:261:46 | call to NewReader | test.go:263:2:263:12 | flateReader | provenance | |
| test.go:261:17:261:46 | call to NewReader | test.go:264:26:264:36 | flateReader | provenance | |
| test.go:261:42:261:45 | file | test.go:261:17:261:46 | call to NewReader | provenance | Config |
| test.go:264:12:264:37 | call to NewReader | test.go:266:18:266:24 | tarRead | provenance | |
| test.go:264:26:264:36 | flateReader | test.go:264:12:264:37 | call to NewReader | provenance | MaD:3 |
| test.go:266:18:266:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:283:17:283:20 | definition of file | test.go:286:41:286:44 | file | provenance | |
| test.go:266:18:266:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:283:17:283:20 | SSA def(file) | test.go:286:41:286:44 | file | provenance | |
| test.go:286:2:286:73 | ... := ...[0] | test.go:288:2:288:12 | flateReader | provenance | |
| test.go:286:2:286:73 | ... := ...[0] | test.go:289:26:289:36 | flateReader | provenance | |
| test.go:286:41:286:44 | file | test.go:286:2:286:73 | ... := ...[0] | provenance | Config |
| test.go:289:12:289:37 | call to NewReader | test.go:291:18:291:24 | tarRead | provenance | |
| test.go:289:26:289:36 | flateReader | test.go:289:12:289:37 | call to NewReader | provenance | MaD:3 |
| test.go:291:18:291:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:308:20:308:23 | definition of file | test.go:311:43:311:46 | file | provenance | |
| test.go:291:18:291:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:308:20:308:23 | SSA def(file) | test.go:311:43:311:46 | file | provenance | |
| test.go:311:2:311:47 | ... := ...[0] | test.go:313:2:313:11 | zlibReader | provenance | |
| test.go:311:2:311:47 | ... := ...[0] | test.go:314:26:314:35 | zlibReader | provenance | |
| test.go:311:43:311:46 | file | test.go:311:2:311:47 | ... := ...[0] | provenance | Config |
| test.go:314:12:314:36 | call to NewReader | test.go:316:18:316:24 | tarRead | provenance | |
| test.go:314:26:314:35 | zlibReader | test.go:314:12:314:36 | call to NewReader | provenance | MaD:3 |
| test.go:316:18:316:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:333:11:333:14 | definition of file | test.go:336:34:336:37 | file | provenance | |
| test.go:316:18:316:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:333:11:333:14 | SSA def(file) | test.go:336:34:336:37 | file | provenance | |
| test.go:336:2:336:38 | ... := ...[0] | test.go:338:2:338:11 | zlibReader | provenance | |
| test.go:336:2:336:38 | ... := ...[0] | test.go:339:26:339:35 | zlibReader | provenance | |
| test.go:336:34:336:37 | file | test.go:336:2:336:38 | ... := ...[0] | provenance | Config |
| test.go:339:12:339:36 | call to NewReader | test.go:341:18:341:24 | tarRead | provenance | |
| test.go:339:26:339:35 | zlibReader | test.go:339:12:339:36 | call to NewReader | provenance | MaD:3 |
| test.go:341:18:341:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:358:13:358:16 | definition of file | test.go:361:35:361:38 | file | provenance | |
| test.go:341:18:341:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:358:13:358:16 | SSA def(file) | test.go:361:35:361:38 | file | provenance | |
| test.go:361:18:361:39 | call to NewReader | test.go:363:2:363:13 | snappyReader | provenance | |
| test.go:361:18:361:39 | call to NewReader | test.go:364:2:364:13 | snappyReader | provenance | |
| test.go:361:18:361:39 | call to NewReader | test.go:365:26:365:37 | snappyReader | provenance | |
| test.go:361:35:361:38 | file | test.go:361:18:361:39 | call to NewReader | provenance | Config |
| test.go:365:12:365:38 | call to NewReader | test.go:367:18:367:24 | tarRead | provenance | |
| test.go:365:26:365:37 | snappyReader | test.go:365:12:365:38 | call to NewReader | provenance | MaD:3 |
| test.go:367:18:367:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:384:22:384:25 | definition of file | test.go:387:44:387:47 | file | provenance | |
| test.go:367:18:367:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:384:22:384:25 | SSA def(file) | test.go:387:44:387:47 | file | provenance | |
| test.go:387:18:387:48 | call to NewReader | test.go:389:2:389:13 | snappyReader | provenance | |
| test.go:387:18:387:48 | call to NewReader | test.go:391:2:391:13 | snappyReader | provenance | |
| test.go:387:18:387:48 | call to NewReader | test.go:392:2:392:13 | snappyReader | provenance | |
@@ -158,8 +158,8 @@ edges
| test.go:387:44:387:47 | file | test.go:387:18:387:48 | call to NewReader | provenance | Config |
| test.go:393:12:393:38 | call to NewReader | test.go:395:18:395:24 | tarRead | provenance | |
| test.go:393:26:393:37 | snappyReader | test.go:393:12:393:38 | call to NewReader | provenance | MaD:3 |
| test.go:395:18:395:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:412:9:412:12 | definition of file | test.go:415:27:415:30 | file | provenance | |
| test.go:395:18:395:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:412:9:412:12 | SSA def(file) | test.go:415:27:415:30 | file | provenance | |
| test.go:415:14:415:31 | call to NewReader | test.go:417:2:417:9 | s2Reader | provenance | |
| test.go:415:14:415:31 | call to NewReader | test.go:418:2:418:9 | s2Reader | provenance | |
| test.go:415:14:415:31 | call to NewReader | test.go:420:2:420:9 | s2Reader | provenance | |
@@ -167,35 +167,35 @@ edges
| test.go:415:27:415:30 | file | test.go:415:14:415:31 | call to NewReader | provenance | Config |
| test.go:421:12:421:34 | call to NewReader | test.go:423:18:423:24 | tarRead | provenance | |
| test.go:421:26:421:33 | s2Reader | test.go:421:12:421:34 | call to NewReader | provenance | MaD:3 |
| test.go:423:18:423:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:440:19:440:21 | definition of src | test.go:441:34:441:36 | src | provenance | |
| test.go:423:18:423:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:440:19:440:21 | SSA def(src) | test.go:441:34:441:36 | src | provenance | |
| test.go:441:2:441:37 | ... := ...[0] | test.go:444:12:444:32 | type conversion | provenance | |
| test.go:441:34:441:36 | src | test.go:441:2:441:37 | ... := ...[0] | provenance | Config |
| test.go:444:12:444:32 | type conversion | test.go:445:23:445:28 | newSrc | provenance | |
| test.go:447:11:447:14 | definition of file | test.go:450:34:450:37 | file | provenance | |
| test.go:447:11:447:14 | SSA def(file) | test.go:450:34:450:37 | file | provenance | |
| test.go:450:2:450:38 | ... := ...[0] | test.go:452:2:452:11 | gzipReader | provenance | |
| test.go:450:2:450:38 | ... := ...[0] | test.go:453:26:453:35 | gzipReader | provenance | |
| test.go:450:34:450:37 | file | test.go:450:2:450:38 | ... := ...[0] | provenance | Config |
| test.go:453:12:453:36 | call to NewReader | test.go:455:18:455:24 | tarRead | provenance | |
| test.go:453:26:453:35 | gzipReader | test.go:453:12:453:36 | call to NewReader | provenance | MaD:3 |
| test.go:455:18:455:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:472:20:472:23 | definition of file | test.go:475:43:475:46 | file | provenance | |
| test.go:455:18:455:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:472:20:472:23 | SSA def(file) | test.go:475:43:475:46 | file | provenance | |
| test.go:475:2:475:47 | ... := ...[0] | test.go:477:2:477:11 | gzipReader | provenance | |
| test.go:475:2:475:47 | ... := ...[0] | test.go:479:2:479:11 | gzipReader | provenance | |
| test.go:475:2:475:47 | ... := ...[0] | test.go:480:26:480:35 | gzipReader | provenance | |
| test.go:475:43:475:46 | file | test.go:475:2:475:47 | ... := ...[0] | provenance | Config |
| test.go:480:12:480:36 | call to NewReader | test.go:482:18:482:24 | tarRead | provenance | |
| test.go:480:26:480:35 | gzipReader | test.go:480:12:480:36 | call to NewReader | provenance | MaD:3 |
| test.go:482:18:482:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:499:20:499:23 | definition of file | test.go:502:45:502:48 | file | provenance | |
| test.go:482:18:482:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:499:20:499:23 | SSA def(file) | test.go:502:45:502:48 | file | provenance | |
| test.go:502:2:502:49 | ... := ...[0] | test.go:504:2:504:12 | pgzipReader | provenance | |
| test.go:502:2:502:49 | ... := ...[0] | test.go:506:2:506:12 | pgzipReader | provenance | |
| test.go:502:2:502:49 | ... := ...[0] | test.go:507:26:507:36 | pgzipReader | provenance | |
| test.go:502:45:502:48 | file | test.go:502:2:502:49 | ... := ...[0] | provenance | Config |
| test.go:507:12:507:37 | call to NewReader | test.go:509:18:509:24 | tarRead | provenance | |
| test.go:507:26:507:36 | pgzipReader | test.go:507:12:507:37 | call to NewReader | provenance | MaD:3 |
| test.go:509:18:509:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:526:21:526:24 | definition of file | test.go:529:43:529:46 | file | provenance | |
| test.go:509:18:509:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:526:21:526:24 | SSA def(file) | test.go:529:43:529:46 | file | provenance | |
| test.go:529:2:529:47 | ... := ...[0] | test.go:531:2:531:11 | zstdReader | provenance | |
| test.go:529:2:529:47 | ... := ...[0] | test.go:533:2:533:11 | zstdReader | provenance | |
| test.go:529:2:529:47 | ... := ...[0] | test.go:535:2:535:11 | zstdReader | provenance | |
@@ -203,33 +203,33 @@ edges
| test.go:529:43:529:46 | file | test.go:529:2:529:47 | ... := ...[0] | provenance | Config |
| test.go:536:12:536:36 | call to NewReader | test.go:538:18:538:24 | tarRead | provenance | |
| test.go:536:26:536:35 | zstdReader | test.go:536:12:536:36 | call to NewReader | provenance | MaD:3 |
| test.go:538:18:538:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:555:19:555:22 | definition of file | test.go:558:38:558:41 | file | provenance | |
| test.go:538:18:538:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:555:19:555:22 | SSA def(file) | test.go:558:38:558:41 | file | provenance | |
| test.go:558:16:558:42 | call to NewReader | test.go:560:2:560:11 | zstdReader | provenance | |
| test.go:558:16:558:42 | call to NewReader | test.go:561:26:561:35 | zstdReader | provenance | |
| test.go:558:38:558:41 | file | test.go:558:16:558:42 | call to NewReader | provenance | Config |
| test.go:561:12:561:36 | call to NewReader | test.go:563:18:563:24 | tarRead | provenance | |
| test.go:561:26:561:35 | zstdReader | test.go:561:12:561:36 | call to NewReader | provenance | MaD:3 |
| test.go:563:18:563:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:580:9:580:12 | definition of file | test.go:583:30:583:33 | file | provenance | |
| test.go:563:18:563:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:580:9:580:12 | SSA def(file) | test.go:583:30:583:33 | file | provenance | |
| test.go:583:2:583:34 | ... := ...[0] | test.go:585:2:585:9 | xzReader | provenance | |
| test.go:583:2:583:34 | ... := ...[0] | test.go:586:26:586:33 | xzReader | provenance | |
| test.go:583:30:583:33 | file | test.go:583:2:583:34 | ... := ...[0] | provenance | Config |
| test.go:586:12:586:34 | call to NewReader | test.go:589:18:589:24 | tarRead | provenance | |
| test.go:586:12:586:34 | call to NewReader | test.go:590:19:590:25 | tarRead | provenance | |
| test.go:586:26:586:33 | xzReader | test.go:586:12:586:34 | call to NewReader | provenance | MaD:3 |
| test.go:589:18:589:24 | tarRead | test.go:611:22:611:28 | definition of tarRead | provenance | |
| test.go:590:19:590:25 | tarRead | test.go:627:23:627:29 | definition of tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | definition of tarRead | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:627:23:627:29 | definition of tarRead | test.go:629:2:629:8 | tarRead | provenance | |
| test.go:589:18:589:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | |
| test.go:590:19:590:25 | tarRead | test.go:627:23:627:29 | SSA def(tarRead) | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | |
| test.go:627:23:627:29 | SSA def(tarRead) | test.go:629:2:629:8 | tarRead | provenance | |
models
| 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual |
| 2 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual |
@@ -258,7 +258,7 @@ nodes
| test.go:89:17:89:28 | selection of Body | semmle.label | selection of Body |
| test.go:91:15:91:26 | selection of Body | semmle.label | selection of Body |
| test.go:93:5:93:16 | selection of Body | semmle.label | selection of Body |
| test.go:128:20:128:27 | definition of filename | semmle.label | definition of filename |
| test.go:128:20:128:27 | SSA def(filename) | semmle.label | SSA def(filename) |
| test.go:130:2:130:41 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:130:33:130:40 | filename | semmle.label | filename |
| test.go:132:3:132:19 | ... := ...[0] | semmle.label | ... := ...[0] |
@@ -269,7 +269,7 @@ nodes
| test.go:145:12:145:12 | f | semmle.label | f |
| test.go:145:12:145:19 | call to Open | semmle.label | call to Open |
| test.go:147:37:147:38 | rc | semmle.label | rc |
| test.go:158:19:158:22 | definition of file | semmle.label | definition of file |
| test.go:158:19:158:22 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:159:2:159:29 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:159:25:159:28 | file | semmle.label | file |
| test.go:160:2:160:69 | ... := ...[0] | semmle.label | ... := ...[0] |
@@ -278,7 +278,7 @@ nodes
| test.go:163:3:163:36 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:163:26:163:29 | file | semmle.label | file |
| test.go:164:36:164:51 | fileReaderCloser | semmle.label | fileReaderCloser |
| test.go:169:28:169:31 | definition of file | semmle.label | definition of file |
| test.go:169:28:169:31 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:170:2:170:29 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:170:25:170:28 | file | semmle.label | file |
| test.go:171:2:171:78 | ... := ...[0] | semmle.label | ... := ...[0] |
@@ -287,56 +287,56 @@ nodes
| test.go:175:26:175:29 | file | semmle.label | file |
| test.go:175:26:175:36 | call to Open | semmle.label | call to Open |
| test.go:176:36:176:51 | fileReaderCloser | semmle.label | fileReaderCloser |
| test.go:181:17:181:20 | definition of file | semmle.label | definition of file |
| test.go:181:17:181:20 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:184:2:184:73 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:184:41:184:44 | file | semmle.label | file |
| test.go:186:2:186:12 | bzip2Reader | semmle.label | bzip2Reader |
| test.go:187:12:187:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:187:26:187:36 | bzip2Reader | semmle.label | bzip2Reader |
| test.go:189:18:189:24 | tarRead | semmle.label | tarRead |
| test.go:208:12:208:15 | definition of file | semmle.label | definition of file |
| test.go:208:12:208:15 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:211:17:211:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:211:33:211:36 | file | semmle.label | file |
| test.go:213:2:213:12 | bzip2Reader | semmle.label | bzip2Reader |
| test.go:214:12:214:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:214:26:214:36 | bzip2Reader | semmle.label | bzip2Reader |
| test.go:216:18:216:24 | tarRead | semmle.label | tarRead |
| test.go:233:12:233:15 | definition of file | semmle.label | definition of file |
| test.go:233:12:233:15 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:236:17:236:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:236:33:236:36 | file | semmle.label | file |
| test.go:238:2:238:12 | flateReader | semmle.label | flateReader |
| test.go:239:12:239:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:239:26:239:36 | flateReader | semmle.label | flateReader |
| test.go:241:18:241:24 | tarRead | semmle.label | tarRead |
| test.go:258:21:258:24 | definition of file | semmle.label | definition of file |
| test.go:258:21:258:24 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:261:17:261:46 | call to NewReader | semmle.label | call to NewReader |
| test.go:261:42:261:45 | file | semmle.label | file |
| test.go:263:2:263:12 | flateReader | semmle.label | flateReader |
| test.go:264:12:264:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:264:26:264:36 | flateReader | semmle.label | flateReader |
| test.go:266:18:266:24 | tarRead | semmle.label | tarRead |
| test.go:283:17:283:20 | definition of file | semmle.label | definition of file |
| test.go:283:17:283:20 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:286:2:286:73 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:286:41:286:44 | file | semmle.label | file |
| test.go:288:2:288:12 | flateReader | semmle.label | flateReader |
| test.go:289:12:289:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:289:26:289:36 | flateReader | semmle.label | flateReader |
| test.go:291:18:291:24 | tarRead | semmle.label | tarRead |
| test.go:308:20:308:23 | definition of file | semmle.label | definition of file |
| test.go:308:20:308:23 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:311:2:311:47 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:311:43:311:46 | file | semmle.label | file |
| test.go:313:2:313:11 | zlibReader | semmle.label | zlibReader |
| test.go:314:12:314:36 | call to NewReader | semmle.label | call to NewReader |
| test.go:314:26:314:35 | zlibReader | semmle.label | zlibReader |
| test.go:316:18:316:24 | tarRead | semmle.label | tarRead |
| test.go:333:11:333:14 | definition of file | semmle.label | definition of file |
| test.go:333:11:333:14 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:336:2:336:38 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:336:34:336:37 | file | semmle.label | file |
| test.go:338:2:338:11 | zlibReader | semmle.label | zlibReader |
| test.go:339:12:339:36 | call to NewReader | semmle.label | call to NewReader |
| test.go:339:26:339:35 | zlibReader | semmle.label | zlibReader |
| test.go:341:18:341:24 | tarRead | semmle.label | tarRead |
| test.go:358:13:358:16 | definition of file | semmle.label | definition of file |
| test.go:358:13:358:16 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:361:18:361:39 | call to NewReader | semmle.label | call to NewReader |
| test.go:361:35:361:38 | file | semmle.label | file |
| test.go:363:2:363:13 | snappyReader | semmle.label | snappyReader |
@@ -344,7 +344,7 @@ nodes
| test.go:365:12:365:38 | call to NewReader | semmle.label | call to NewReader |
| test.go:365:26:365:37 | snappyReader | semmle.label | snappyReader |
| test.go:367:18:367:24 | tarRead | semmle.label | tarRead |
| test.go:384:22:384:25 | definition of file | semmle.label | definition of file |
| test.go:384:22:384:25 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:387:18:387:48 | call to NewReader | semmle.label | call to NewReader |
| test.go:387:44:387:47 | file | semmle.label | file |
| test.go:389:2:389:13 | snappyReader | semmle.label | snappyReader |
@@ -353,7 +353,7 @@ nodes
| test.go:393:12:393:38 | call to NewReader | semmle.label | call to NewReader |
| test.go:393:26:393:37 | snappyReader | semmle.label | snappyReader |
| test.go:395:18:395:24 | tarRead | semmle.label | tarRead |
| test.go:412:9:412:12 | definition of file | semmle.label | definition of file |
| test.go:412:9:412:12 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:415:14:415:31 | call to NewReader | semmle.label | call to NewReader |
| test.go:415:27:415:30 | file | semmle.label | file |
| test.go:417:2:417:9 | s2Reader | semmle.label | s2Reader |
@@ -362,19 +362,19 @@ nodes
| test.go:421:12:421:34 | call to NewReader | semmle.label | call to NewReader |
| test.go:421:26:421:33 | s2Reader | semmle.label | s2Reader |
| test.go:423:18:423:24 | tarRead | semmle.label | tarRead |
| test.go:440:19:440:21 | definition of src | semmle.label | definition of src |
| test.go:440:19:440:21 | SSA def(src) | semmle.label | SSA def(src) |
| test.go:441:2:441:37 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:441:34:441:36 | src | semmle.label | src |
| test.go:444:12:444:32 | type conversion | semmle.label | type conversion |
| test.go:445:23:445:28 | newSrc | semmle.label | newSrc |
| test.go:447:11:447:14 | definition of file | semmle.label | definition of file |
| test.go:447:11:447:14 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:450:2:450:38 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:450:34:450:37 | file | semmle.label | file |
| test.go:452:2:452:11 | gzipReader | semmle.label | gzipReader |
| test.go:453:12:453:36 | call to NewReader | semmle.label | call to NewReader |
| test.go:453:26:453:35 | gzipReader | semmle.label | gzipReader |
| test.go:455:18:455:24 | tarRead | semmle.label | tarRead |
| test.go:472:20:472:23 | definition of file | semmle.label | definition of file |
| test.go:472:20:472:23 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:475:2:475:47 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:475:43:475:46 | file | semmle.label | file |
| test.go:477:2:477:11 | gzipReader | semmle.label | gzipReader |
@@ -382,7 +382,7 @@ nodes
| test.go:480:12:480:36 | call to NewReader | semmle.label | call to NewReader |
| test.go:480:26:480:35 | gzipReader | semmle.label | gzipReader |
| test.go:482:18:482:24 | tarRead | semmle.label | tarRead |
| test.go:499:20:499:23 | definition of file | semmle.label | definition of file |
| test.go:499:20:499:23 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:502:2:502:49 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:502:45:502:48 | file | semmle.label | file |
| test.go:504:2:504:12 | pgzipReader | semmle.label | pgzipReader |
@@ -390,7 +390,7 @@ nodes
| test.go:507:12:507:37 | call to NewReader | semmle.label | call to NewReader |
| test.go:507:26:507:36 | pgzipReader | semmle.label | pgzipReader |
| test.go:509:18:509:24 | tarRead | semmle.label | tarRead |
| test.go:526:21:526:24 | definition of file | semmle.label | definition of file |
| test.go:526:21:526:24 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:529:2:529:47 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:529:43:529:46 | file | semmle.label | file |
| test.go:531:2:531:11 | zstdReader | semmle.label | zstdReader |
@@ -399,14 +399,14 @@ nodes
| test.go:536:12:536:36 | call to NewReader | semmle.label | call to NewReader |
| test.go:536:26:536:35 | zstdReader | semmle.label | zstdReader |
| test.go:538:18:538:24 | tarRead | semmle.label | tarRead |
| test.go:555:19:555:22 | definition of file | semmle.label | definition of file |
| test.go:555:19:555:22 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:558:16:558:42 | call to NewReader | semmle.label | call to NewReader |
| test.go:558:38:558:41 | file | semmle.label | file |
| test.go:560:2:560:11 | zstdReader | semmle.label | zstdReader |
| test.go:561:12:561:36 | call to NewReader | semmle.label | call to NewReader |
| test.go:561:26:561:35 | zstdReader | semmle.label | zstdReader |
| test.go:563:18:563:24 | tarRead | semmle.label | tarRead |
| test.go:580:9:580:12 | definition of file | semmle.label | definition of file |
| test.go:580:9:580:12 | SSA def(file) | semmle.label | SSA def(file) |
| test.go:583:2:583:34 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:583:30:583:33 | file | semmle.label | file |
| test.go:585:2:585:9 | xzReader | semmle.label | xzReader |
@@ -414,15 +414,15 @@ nodes
| test.go:586:26:586:33 | xzReader | semmle.label | xzReader |
| test.go:589:18:589:24 | tarRead | semmle.label | tarRead |
| test.go:590:19:590:25 | tarRead | semmle.label | tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:621:25:621:31 | tarRead | semmle.label | tarRead |
| test.go:621:25:621:31 | tarRead | semmle.label | tarRead |
| test.go:621:25:621:31 | tarRead | semmle.label | tarRead |
@@ -432,6 +432,6 @@ nodes
| test.go:621:25:621:31 | tarRead | semmle.label | tarRead |
| test.go:621:25:621:31 | tarRead | semmle.label | tarRead |
| test.go:621:25:621:31 | tarRead | semmle.label | tarRead |
| test.go:627:23:627:29 | definition of tarRead | semmle.label | definition of tarRead |
| test.go:627:23:627:29 | SSA def(tarRead) | semmle.label | SSA def(tarRead) |
| test.go:629:2:629:8 | tarRead | semmle.label | tarRead |
subpaths

View File

@@ -22,8 +22,8 @@ edges
| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:236:21:236:23 | definition of req | provenance | |
| WrongUsageOfUnsafe.go:236:21:236:23 | definition of req | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | provenance | |
| WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | provenance | |
@@ -51,7 +51,7 @@ nodes
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:236:21:236:23 | definition of req | semmle.label | definition of req |
| WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | semmle.label | SSA def(req) |
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | semmle.label | type conversion |

View File

@@ -1,6 +1,6 @@
module codeql-go-tests/concepts/loggercall
go 1.15
go 1.21
require (
github.com/golang/glog v1.2.5

View File

@@ -2,10 +2,12 @@ package main
const fmt = "formatted %s string"
const text = "test"
const key = "key"
var v []byte
func main() {
glogTest(len(v))
stdlib()
slogTest()
}

View File

@@ -0,0 +1,40 @@
package main
import (
"context"
"log/slog"
)
func slogTest() {
ctx := context.Background()
var logger *slog.Logger
var attr slog.Attr
// Methods on *slog.Logger: Debug/Info/Warn/Error(msg string, args ...any).
logger.Debug(text) // $ logger=text
logger.Info(text) // $ logger=text
logger.Warn(text) // $ logger=text
logger.Error(text) // $ logger=text
logger.Info(text, key, v) // $ logger=text logger=key logger=v
// Context variants: (ctx, msg string, args ...any).
logger.DebugContext(ctx, text) // $ logger=text
logger.InfoContext(ctx, text) // $ logger=text
logger.WarnContext(ctx, text) // $ logger=text
logger.ErrorContext(ctx, text) // $ logger=text
logger.InfoContext(ctx, text, key, v) // $ logger=text logger=key logger=v
// Log/LogAttrs: (ctx, level, msg string, args/attrs ...).
logger.Log(ctx, slog.LevelInfo, text, key, v) // $ logger=text logger=key logger=v
logger.LogAttrs(ctx, slog.LevelInfo, text, attr) // $ logger=text logger=attr
// Package-level convenience functions.
slog.Debug(text) // $ logger=text
slog.Info(text) // $ logger=text
slog.Warn(text) // $ logger=text
slog.Error(text) // $ logger=text
slog.Info(text, key, v) // $ logger=text logger=key logger=v
slog.InfoContext(ctx, text, key, v) // $ logger=text logger=key logger=v
slog.Log(ctx, slog.LevelInfo, text, key, v) // $ logger=text logger=key logger=v
slog.LogAttrs(ctx, slog.LevelInfo, text, attr) // $ logger=text logger=attr
}

View File

@@ -3,7 +3,7 @@
| stdlib.go:13:21:13:24 | "ab" | ab | stdlib.go:13:21:13:24 | "ab" |
| stdlib.go:15:26:15:39 | "[so]me\|regex" | [so]me\|regex | stdlib.go:15:2:15:40 | ... := ...[0] |
| stdlib.go:15:26:15:39 | "[so]me\|regex" | [so]me\|regex | stdlib.go:15:26:15:39 | "[so]me\|regex" |
| stdlib.go:16:30:16:37 | "posix?" | posix? | stdlib.go:16:2:16:3 | definition of re |
| stdlib.go:16:30:16:37 | "posix?" | posix? | stdlib.go:16:2:16:3 | SSA def(re) |
| stdlib.go:16:30:16:37 | "posix?" | posix? | stdlib.go:16:2:16:38 | ... = ...[0] |
| stdlib.go:16:30:16:37 | "posix?" | posix? | stdlib.go:16:30:16:37 | "posix?" |
| stdlib.go:16:30:16:37 | "posix?" | posix? | stdlib.go:17:2:17:3 | re |

View File

@@ -735,129 +735,153 @@
| main.go:48:11:48:12 | 42 | main.go:48:2:48:7 | assignment to result |
| main.go:49:2:49:7 | return statement | main.go:47:13:47:18 | implicit read of result |
| main.go:52:1:54:1 | entry | main.go:52:14:52:19 | zero value for result |
| main.go:52:1:54:1 | function declaration | main.go:56:6:56:10 | skip |
| main.go:52:1:54:1 | function declaration | main.go:56:6:56:9 | skip |
| main.go:52:6:52:9 | skip | main.go:52:1:54:1 | function declaration |
| main.go:52:14:52:19 | implicit read of result | main.go:52:1:54:1 | exit |
| main.go:52:14:52:19 | initialization of result | main.go:53:2:53:7 | return statement |
| main.go:52:14:52:19 | zero value for result | main.go:52:14:52:19 | initialization of result |
| main.go:53:2:53:7 | return statement | main.go:52:14:52:19 | implicit read of result |
| main.go:56:1:80:1 | entry | main.go:57:6:57:6 | skip |
| main.go:56:1:80:1 | function declaration | main.go:82:6:82:13 | skip |
| main.go:56:6:56:10 | skip | main.go:56:1:80:1 | function declaration |
| main.go:57:6:57:6 | assignment to x | main.go:58:6:58:9 | cond |
| main.go:57:6:57:6 | skip | main.go:57:6:57:6 | zero value for x |
| main.go:57:6:57:6 | zero value for x | main.go:57:6:57:6 | assignment to x |
| main.go:58:6:58:9 | cond | main.go:58:6:58:11 | call to cond |
| main.go:58:6:58:11 | call to cond | main.go:56:1:80:1 | exit |
| main.go:58:6:58:11 | call to cond | main.go:58:6:58:11 | call to cond is false |
| main.go:58:6:58:11 | call to cond | main.go:58:6:58:11 | call to cond is true |
| main.go:58:6:58:11 | call to cond is false | main.go:61:2:61:10 | selection of Print |
| main.go:58:6:58:11 | call to cond is true | main.go:59:3:59:3 | skip |
| main.go:59:3:59:3 | assignment to x | main.go:58:6:58:9 | cond |
| main.go:59:3:59:3 | skip | main.go:59:7:59:7 | 2 |
| main.go:59:7:59:7 | 2 | main.go:59:3:59:3 | assignment to x |
| main.go:61:2:61:10 | selection of Print | main.go:61:12:61:12 | x |
| main.go:61:2:61:13 | call to Print | main.go:56:1:80:1 | exit |
| main.go:61:2:61:13 | call to Print | main.go:63:2:63:2 | skip |
| main.go:61:12:61:12 | x | main.go:61:2:61:13 | call to Print |
| main.go:63:2:63:2 | assignment to y | main.go:64:6:64:6 | skip |
| main.go:63:2:63:2 | skip | main.go:63:7:63:7 | 1 |
| main.go:63:7:63:7 | 1 | main.go:63:2:63:2 | assignment to y |
| main.go:64:6:64:6 | assignment to i | main.go:65:6:65:9 | cond |
| main.go:64:6:64:6 | skip | main.go:64:11:64:11 | 0 |
| main.go:64:11:64:11 | 0 | main.go:64:6:64:6 | assignment to i |
| main.go:64:16:64:16 | i | main.go:64:16:64:18 | 1 |
| main.go:64:16:64:18 | 1 | main.go:64:16:64:18 | rhs of increment statement |
| main.go:64:16:64:18 | increment statement | main.go:65:6:65:9 | cond |
| main.go:64:16:64:18 | rhs of increment statement | main.go:64:16:64:18 | increment statement |
| main.go:65:6:65:9 | cond | main.go:65:6:65:11 | call to cond |
| main.go:65:6:65:11 | call to cond | main.go:56:1:80:1 | exit |
| main.go:65:6:65:11 | call to cond | main.go:65:6:65:11 | call to cond is false |
| main.go:65:6:65:11 | call to cond | main.go:65:6:65:11 | call to cond is true |
| main.go:65:6:65:11 | call to cond is false | main.go:68:3:68:3 | skip |
| main.go:65:6:65:11 | call to cond is true | main.go:66:4:66:8 | skip |
| main.go:66:4:66:8 | skip | main.go:70:2:70:10 | selection of Print |
| main.go:68:3:68:3 | assignment to y | main.go:64:16:64:16 | i |
| main.go:68:3:68:3 | skip | main.go:68:7:68:7 | 2 |
| main.go:68:7:68:7 | 2 | main.go:68:3:68:3 | assignment to y |
| main.go:70:2:70:10 | selection of Print | main.go:70:12:70:12 | y |
| main.go:70:2:70:13 | call to Print | main.go:56:1:80:1 | exit |
| main.go:70:2:70:13 | call to Print | main.go:72:2:72:2 | skip |
| main.go:70:12:70:12 | y | main.go:70:2:70:13 | call to Print |
| main.go:72:2:72:2 | assignment to z | main.go:73:6:73:6 | skip |
| main.go:72:2:72:2 | skip | main.go:72:7:72:7 | 1 |
| main.go:72:7:72:7 | 1 | main.go:72:2:72:2 | assignment to z |
| main.go:73:6:73:6 | assignment to i | main.go:74:3:74:3 | skip |
| main.go:73:6:73:6 | skip | main.go:73:11:73:11 | 0 |
| main.go:73:11:73:11 | 0 | main.go:73:6:73:6 | assignment to i |
| main.go:73:16:73:16 | i | main.go:73:16:73:18 | 1 |
| main.go:73:16:73:18 | 1 | main.go:73:16:73:18 | rhs of increment statement |
| main.go:73:16:73:18 | increment statement | main.go:74:3:74:3 | skip |
| main.go:73:16:73:18 | rhs of increment statement | main.go:73:16:73:18 | increment statement |
| main.go:74:3:74:3 | assignment to z | main.go:75:6:75:9 | cond |
| main.go:74:3:74:3 | skip | main.go:74:7:74:7 | 2 |
| main.go:74:7:74:7 | 2 | main.go:74:3:74:3 | assignment to z |
| main.go:56:1:64:1 | entry | main.go:56:11:56:18 | argument corresponding to selector |
| main.go:56:1:64:1 | function declaration | main.go:66:6:66:10 | skip |
| main.go:56:6:56:9 | skip | main.go:56:1:64:1 | function declaration |
| main.go:56:11:56:18 | argument corresponding to selector | main.go:56:11:56:18 | initialization of selector |
| main.go:56:11:56:18 | initialization of selector | main.go:56:26:56:31 | zero value for result |
| main.go:56:26:56:31 | implicit read of result | main.go:56:1:64:1 | exit |
| main.go:56:26:56:31 | initialization of result | main.go:57:2:57:7 | skip |
| main.go:56:26:56:31 | zero value for result | main.go:56:26:56:31 | initialization of result |
| main.go:57:2:57:7 | assignment to result | main.go:58:5:58:12 | selector |
| main.go:57:2:57:7 | skip | main.go:57:11:57:11 | 0 |
| main.go:57:11:57:11 | 0 | main.go:57:2:57:7 | assignment to result |
| main.go:58:5:58:12 | selector | main.go:58:17:58:17 | 1 |
| main.go:58:5:58:17 | ...==... | main.go:58:5:58:17 | ...==... is false |
| main.go:58:5:58:17 | ...==... | main.go:58:5:58:17 | ...==... is true |
| main.go:58:5:58:17 | ...==... is false | main.go:61:3:61:8 | skip |
| main.go:58:5:58:17 | ...==... is true | main.go:59:10:59:10 | 1 |
| main.go:58:17:58:17 | 1 | main.go:58:5:58:17 | ...==... |
| main.go:59:3:59:10 | return statement | main.go:56:26:56:31 | implicit read of result |
| main.go:59:10:59:10 | 1 | main.go:59:10:59:10 | implicit write of result |
| main.go:59:10:59:10 | implicit write of result | main.go:59:3:59:10 | return statement |
| main.go:61:3:61:8 | assignment to result | main.go:63:2:63:7 | return statement |
| main.go:61:3:61:8 | skip | main.go:61:12:61:12 | 2 |
| main.go:61:12:61:12 | 2 | main.go:61:3:61:8 | assignment to result |
| main.go:63:2:63:7 | return statement | main.go:56:26:56:31 | implicit read of result |
| main.go:66:1:90:1 | entry | main.go:67:6:67:6 | skip |
| main.go:66:1:90:1 | function declaration | main.go:92:6:92:13 | skip |
| main.go:66:6:66:10 | skip | main.go:66:1:90:1 | function declaration |
| main.go:67:6:67:6 | assignment to x | main.go:68:6:68:9 | cond |
| main.go:67:6:67:6 | skip | main.go:67:6:67:6 | zero value for x |
| main.go:67:6:67:6 | zero value for x | main.go:67:6:67:6 | assignment to x |
| main.go:68:6:68:9 | cond | main.go:68:6:68:11 | call to cond |
| main.go:68:6:68:11 | call to cond | main.go:66:1:90:1 | exit |
| main.go:68:6:68:11 | call to cond | main.go:68:6:68:11 | call to cond is false |
| main.go:68:6:68:11 | call to cond | main.go:68:6:68:11 | call to cond is true |
| main.go:68:6:68:11 | call to cond is false | main.go:71:2:71:10 | selection of Print |
| main.go:68:6:68:11 | call to cond is true | main.go:69:3:69:3 | skip |
| main.go:69:3:69:3 | assignment to x | main.go:68:6:68:9 | cond |
| main.go:69:3:69:3 | skip | main.go:69:7:69:7 | 2 |
| main.go:69:7:69:7 | 2 | main.go:69:3:69:3 | assignment to x |
| main.go:71:2:71:10 | selection of Print | main.go:71:12:71:12 | x |
| main.go:71:2:71:13 | call to Print | main.go:66:1:90:1 | exit |
| main.go:71:2:71:13 | call to Print | main.go:73:2:73:2 | skip |
| main.go:71:12:71:12 | x | main.go:71:2:71:13 | call to Print |
| main.go:73:2:73:2 | assignment to y | main.go:74:6:74:6 | skip |
| main.go:73:2:73:2 | skip | main.go:73:7:73:7 | 1 |
| main.go:73:7:73:7 | 1 | main.go:73:2:73:2 | assignment to y |
| main.go:74:6:74:6 | assignment to i | main.go:75:6:75:9 | cond |
| main.go:74:6:74:6 | skip | main.go:74:11:74:11 | 0 |
| main.go:74:11:74:11 | 0 | main.go:74:6:74:6 | assignment to i |
| main.go:74:16:74:16 | i | main.go:74:16:74:18 | 1 |
| main.go:74:16:74:18 | 1 | main.go:74:16:74:18 | rhs of increment statement |
| main.go:74:16:74:18 | increment statement | main.go:75:6:75:9 | cond |
| main.go:74:16:74:18 | rhs of increment statement | main.go:74:16:74:18 | increment statement |
| main.go:75:6:75:9 | cond | main.go:75:6:75:11 | call to cond |
| main.go:75:6:75:11 | call to cond | main.go:56:1:80:1 | exit |
| main.go:75:6:75:11 | call to cond | main.go:66:1:90:1 | exit |
| main.go:75:6:75:11 | call to cond | main.go:75:6:75:11 | call to cond is false |
| main.go:75:6:75:11 | call to cond | main.go:75:6:75:11 | call to cond is true |
| main.go:75:6:75:11 | call to cond is false | main.go:73:16:73:16 | i |
| main.go:75:6:75:11 | call to cond is false | main.go:78:3:78:3 | skip |
| main.go:75:6:75:11 | call to cond is true | main.go:76:4:76:8 | skip |
| main.go:76:4:76:8 | skip | main.go:79:2:79:10 | selection of Print |
| main.go:79:2:79:10 | selection of Print | main.go:79:12:79:12 | z |
| main.go:79:2:79:13 | call to Print | main.go:56:1:80:1 | exit |
| main.go:79:12:79:12 | z | main.go:79:2:79:13 | call to Print |
| main.go:82:1:86:1 | entry | main.go:82:18:82:18 | zero value for a |
| main.go:82:1:86:1 | function declaration | main.go:88:6:88:23 | skip |
| main.go:82:6:82:13 | skip | main.go:82:1:86:1 | function declaration |
| main.go:82:18:82:18 | implicit read of a | main.go:82:25:82:25 | implicit read of b |
| main.go:82:18:82:18 | initialization of a | main.go:82:25:82:25 | zero value for b |
| main.go:82:18:82:18 | zero value for a | main.go:82:18:82:18 | initialization of a |
| main.go:82:25:82:25 | implicit read of b | main.go:82:1:86:1 | exit |
| main.go:82:25:82:25 | initialization of b | main.go:83:2:83:2 | skip |
| main.go:82:25:82:25 | zero value for b | main.go:82:25:82:25 | initialization of b |
| main.go:83:2:83:2 | assignment to x | main.go:84:2:84:2 | skip |
| main.go:83:2:83:2 | skip | main.go:83:7:83:8 | 23 |
| main.go:83:7:83:8 | 23 | main.go:83:2:83:2 | assignment to x |
| main.go:84:2:84:2 | assignment to x | main.go:84:5:84:5 | assignment to a |
| main.go:84:2:84:2 | skip | main.go:84:5:84:5 | skip |
| main.go:84:5:84:5 | assignment to a | main.go:85:2:85:7 | return statement |
| main.go:84:5:84:5 | skip | main.go:84:9:84:9 | x |
| main.go:84:9:84:9 | x | main.go:84:11:84:12 | 19 |
| main.go:84:9:84:12 | ...+... | main.go:84:15:84:15 | x |
| main.go:84:11:84:12 | 19 | main.go:84:9:84:12 | ...+... |
| main.go:84:15:84:15 | x | main.go:84:2:84:2 | assignment to x |
| main.go:85:2:85:7 | return statement | main.go:82:18:82:18 | implicit read of a |
| main.go:88:1:96:1 | entry | main.go:88:25:88:25 | argument corresponding to x |
| main.go:88:1:96:1 | function declaration | main.go:0:0:0:0 | exit |
| main.go:88:6:88:23 | skip | main.go:88:1:96:1 | function declaration |
| main.go:88:25:88:25 | argument corresponding to x | main.go:88:25:88:25 | initialization of x |
| main.go:88:25:88:25 | initialization of x | main.go:89:2:89:2 | skip |
| main.go:89:2:89:2 | assignment to a | main.go:89:5:89:5 | assignment to b |
| main.go:89:2:89:2 | skip | main.go:89:5:89:5 | skip |
| main.go:89:5:89:5 | assignment to b | main.go:90:5:90:8 | cond |
| main.go:89:5:89:5 | skip | main.go:89:10:89:10 | x |
| main.go:89:10:89:10 | x | main.go:89:13:89:13 | 0 |
| main.go:89:13:89:13 | 0 | main.go:89:2:89:2 | assignment to a |
| main.go:90:5:90:8 | cond | main.go:90:5:90:10 | call to cond |
| main.go:90:5:90:10 | call to cond | main.go:88:1:96:1 | exit |
| main.go:90:5:90:10 | call to cond | main.go:90:5:90:10 | call to cond is false |
| main.go:90:5:90:10 | call to cond | main.go:90:5:90:10 | call to cond is true |
| main.go:90:5:90:10 | call to cond is false | main.go:93:3:93:3 | skip |
| main.go:90:5:90:10 | call to cond is true | main.go:91:3:91:3 | skip |
| main.go:91:3:91:3 | assignment to a | main.go:95:9:95:9 | a |
| main.go:91:3:91:3 | skip | main.go:91:6:91:6 | skip |
| main.go:91:6:91:6 | skip | main.go:91:10:91:10 | b |
| main.go:91:10:91:10 | b | main.go:91:13:91:13 | a |
| main.go:91:13:91:13 | a | main.go:91:3:91:3 | assignment to a |
| main.go:93:3:93:3 | skip | main.go:93:6:93:6 | skip |
| main.go:93:6:93:6 | assignment to b | main.go:95:9:95:9 | a |
| main.go:93:6:93:6 | skip | main.go:93:10:93:10 | b |
| main.go:93:10:93:10 | b | main.go:93:13:93:13 | a |
| main.go:93:13:93:13 | a | main.go:93:6:93:6 | assignment to b |
| main.go:95:2:95:12 | return statement | main.go:88:1:96:1 | exit |
| main.go:95:9:95:9 | a | main.go:95:12:95:12 | b |
| main.go:95:12:95:12 | b | main.go:95:2:95:12 | return statement |
| main.go:76:4:76:8 | skip | main.go:80:2:80:10 | selection of Print |
| main.go:78:3:78:3 | assignment to y | main.go:74:16:74:16 | i |
| main.go:78:3:78:3 | skip | main.go:78:7:78:7 | 2 |
| main.go:78:7:78:7 | 2 | main.go:78:3:78:3 | assignment to y |
| main.go:80:2:80:10 | selection of Print | main.go:80:12:80:12 | y |
| main.go:80:2:80:13 | call to Print | main.go:66:1:90:1 | exit |
| main.go:80:2:80:13 | call to Print | main.go:82:2:82:2 | skip |
| main.go:80:12:80:12 | y | main.go:80:2:80:13 | call to Print |
| main.go:82:2:82:2 | assignment to z | main.go:83:6:83:6 | skip |
| main.go:82:2:82:2 | skip | main.go:82:7:82:7 | 1 |
| main.go:82:7:82:7 | 1 | main.go:82:2:82:2 | assignment to z |
| main.go:83:6:83:6 | assignment to i | main.go:84:3:84:3 | skip |
| main.go:83:6:83:6 | skip | main.go:83:11:83:11 | 0 |
| main.go:83:11:83:11 | 0 | main.go:83:6:83:6 | assignment to i |
| main.go:83:16:83:16 | i | main.go:83:16:83:18 | 1 |
| main.go:83:16:83:18 | 1 | main.go:83:16:83:18 | rhs of increment statement |
| main.go:83:16:83:18 | increment statement | main.go:84:3:84:3 | skip |
| main.go:83:16:83:18 | rhs of increment statement | main.go:83:16:83:18 | increment statement |
| main.go:84:3:84:3 | assignment to z | main.go:85:6:85:9 | cond |
| main.go:84:3:84:3 | skip | main.go:84:7:84:7 | 2 |
| main.go:84:7:84:7 | 2 | main.go:84:3:84:3 | assignment to z |
| main.go:85:6:85:9 | cond | main.go:85:6:85:11 | call to cond |
| main.go:85:6:85:11 | call to cond | main.go:66:1:90:1 | exit |
| main.go:85:6:85:11 | call to cond | main.go:85:6:85:11 | call to cond is false |
| main.go:85:6:85:11 | call to cond | main.go:85:6:85:11 | call to cond is true |
| main.go:85:6:85:11 | call to cond is false | main.go:83:16:83:16 | i |
| main.go:85:6:85:11 | call to cond is true | main.go:86:4:86:8 | skip |
| main.go:86:4:86:8 | skip | main.go:89:2:89:10 | selection of Print |
| main.go:89:2:89:10 | selection of Print | main.go:89:12:89:12 | z |
| main.go:89:2:89:13 | call to Print | main.go:66:1:90:1 | exit |
| main.go:89:12:89:12 | z | main.go:89:2:89:13 | call to Print |
| main.go:92:1:96:1 | entry | main.go:92:18:92:18 | zero value for a |
| main.go:92:1:96:1 | function declaration | main.go:98:6:98:23 | skip |
| main.go:92:6:92:13 | skip | main.go:92:1:96:1 | function declaration |
| main.go:92:18:92:18 | implicit read of a | main.go:92:25:92:25 | implicit read of b |
| main.go:92:18:92:18 | initialization of a | main.go:92:25:92:25 | zero value for b |
| main.go:92:18:92:18 | zero value for a | main.go:92:18:92:18 | initialization of a |
| main.go:92:25:92:25 | implicit read of b | main.go:92:1:96:1 | exit |
| main.go:92:25:92:25 | initialization of b | main.go:93:2:93:2 | skip |
| main.go:92:25:92:25 | zero value for b | main.go:92:25:92:25 | initialization of b |
| main.go:93:2:93:2 | assignment to x | main.go:94:2:94:2 | skip |
| main.go:93:2:93:2 | skip | main.go:93:7:93:8 | 23 |
| main.go:93:7:93:8 | 23 | main.go:93:2:93:2 | assignment to x |
| main.go:94:2:94:2 | assignment to x | main.go:94:5:94:5 | assignment to a |
| main.go:94:2:94:2 | skip | main.go:94:5:94:5 | skip |
| main.go:94:5:94:5 | assignment to a | main.go:95:2:95:7 | return statement |
| main.go:94:5:94:5 | skip | main.go:94:9:94:9 | x |
| main.go:94:9:94:9 | x | main.go:94:11:94:12 | 19 |
| main.go:94:9:94:12 | ...+... | main.go:94:15:94:15 | x |
| main.go:94:11:94:12 | 19 | main.go:94:9:94:12 | ...+... |
| main.go:94:15:94:15 | x | main.go:94:2:94:2 | assignment to x |
| main.go:95:2:95:7 | return statement | main.go:92:18:92:18 | implicit read of a |
| main.go:98:1:106:1 | entry | main.go:98:25:98:25 | argument corresponding to x |
| main.go:98:1:106:1 | function declaration | main.go:0:0:0:0 | exit |
| main.go:98:6:98:23 | skip | main.go:98:1:106:1 | function declaration |
| main.go:98:25:98:25 | argument corresponding to x | main.go:98:25:98:25 | initialization of x |
| main.go:98:25:98:25 | initialization of x | main.go:99:2:99:2 | skip |
| main.go:99:2:99:2 | assignment to a | main.go:99:5:99:5 | assignment to b |
| main.go:99:2:99:2 | skip | main.go:99:5:99:5 | skip |
| main.go:99:5:99:5 | assignment to b | main.go:100:5:100:8 | cond |
| main.go:99:5:99:5 | skip | main.go:99:10:99:10 | x |
| main.go:99:10:99:10 | x | main.go:99:13:99:13 | 0 |
| main.go:99:13:99:13 | 0 | main.go:99:2:99:2 | assignment to a |
| main.go:100:5:100:8 | cond | main.go:100:5:100:10 | call to cond |
| main.go:100:5:100:10 | call to cond | main.go:98:1:106:1 | exit |
| main.go:100:5:100:10 | call to cond | main.go:100:5:100:10 | call to cond is false |
| main.go:100:5:100:10 | call to cond | main.go:100:5:100:10 | call to cond is true |
| main.go:100:5:100:10 | call to cond is false | main.go:103:3:103:3 | skip |
| main.go:100:5:100:10 | call to cond is true | main.go:101:3:101:3 | skip |
| main.go:101:3:101:3 | assignment to a | main.go:105:9:105:9 | a |
| main.go:101:3:101:3 | skip | main.go:101:6:101:6 | skip |
| main.go:101:6:101:6 | skip | main.go:101:10:101:10 | b |
| main.go:101:10:101:10 | b | main.go:101:13:101:13 | a |
| main.go:101:13:101:13 | a | main.go:101:3:101:3 | assignment to a |
| main.go:103:3:103:3 | skip | main.go:103:6:103:6 | skip |
| main.go:103:6:103:6 | assignment to b | main.go:105:9:105:9 | a |
| main.go:103:6:103:6 | skip | main.go:103:10:103:10 | b |
| main.go:103:10:103:10 | b | main.go:103:13:103:13 | a |
| main.go:103:13:103:13 | a | main.go:103:6:103:6 | assignment to b |
| main.go:105:2:105:12 | return statement | main.go:98:1:106:1 | exit |
| main.go:105:9:105:9 | a | main.go:105:12:105:12 | b |
| main.go:105:12:105:12 | b | main.go:105:2:105:12 | return statement |
| noretfunctions.go:0:0:0:0 | entry | noretfunctions.go:3:1:6:1 | skip |
| noretfunctions.go:3:1:6:1 | skip | noretfunctions.go:8:6:8:12 | skip |
| noretfunctions.go:8:1:10:1 | entry | noretfunctions.go:9:2:9:8 | selection of Exit |

View File

@@ -53,6 +53,16 @@ func baz2() (result int) {
return
}
func baz3(selector int) (result int) {
result = 0
if selector == 1 {
return 1
} else {
result = 2
}
return
}
func loops() {
var x int
for cond() {

View File

@@ -22,4 +22,4 @@ invalidModelRow
| test.go:187:24:187:31 | call to Src1 | qltest |
| test.go:191:24:191:31 | call to Src1 | qltest |
| test.go:201:10:201:28 | selection of SourceVariable | qltest |
| test.go:208:15:208:17 | definition of src | qltest |
| test.go:208:15:208:17 | SSA def(src) | qltest |

View File

@@ -22,4 +22,4 @@ invalidModelRow
| test.go:187:24:187:31 | call to Src1 | qltest |
| test.go:191:24:191:31 | call to Src1 | qltest |
| test.go:209:10:209:28 | selection of SourceVariable | qltest |
| test.go:216:15:216:17 | definition of src | qltest |
| test.go:216:15:216:17 | SSA def(src) | qltest |

View File

@@ -1,169 +1,169 @@
| main.go:3:12:3:12 | argument corresponding to x | main.go:3:12:3:12 | definition of x |
| main.go:3:12:3:12 | definition of x | main.go:5:5:5:5 | x |
| main.go:3:19:3:20 | argument corresponding to fn | main.go:3:19:3:20 | definition of fn |
| main.go:3:19:3:20 | definition of fn | main.go:10:24:10:25 | fn |
| main.go:3:12:3:12 | SSA def(x) | main.go:5:5:5:5 | x |
| main.go:3:12:3:12 | argument corresponding to x | main.go:3:12:3:12 | SSA def(x) |
| main.go:3:19:3:20 | SSA def(fn) | main.go:10:24:10:25 | fn |
| main.go:3:19:3:20 | argument corresponding to fn | main.go:3:19:3:20 | SSA def(fn) |
| main.go:5:5:5:5 | x | main.go:6:7:6:7 | x |
| main.go:5:5:5:5 | x | main.go:8:8:8:8 | x |
| main.go:6:3:6:3 | definition of y | main.go:10:12:10:12 | y |
| main.go:6:7:6:7 | x | main.go:6:3:6:3 | definition of y |
| main.go:6:3:6:3 | SSA def(y) | main.go:10:12:10:12 | y |
| main.go:6:7:6:7 | x | main.go:6:3:6:3 | SSA def(y) |
| main.go:6:7:6:7 | x | main.go:10:7:10:7 | x |
| main.go:8:3:8:3 | definition of y | main.go:10:12:10:12 | y |
| main.go:8:7:8:8 | -... | main.go:8:3:8:3 | definition of y |
| main.go:8:3:8:3 | SSA def(y) | main.go:10:12:10:12 | y |
| main.go:8:7:8:8 | -... | main.go:8:3:8:3 | SSA def(y) |
| main.go:8:8:8:8 | x | main.go:10:7:10:7 | x |
| main.go:10:2:10:2 | definition of z | main.go:11:14:11:14 | z |
| main.go:10:2:10:2 | SSA def(z) | main.go:11:14:11:14 | z |
| main.go:10:7:10:7 | x | main.go:10:22:10:22 | x |
| main.go:10:7:10:12 | ...<=... | main.go:10:7:10:27 | ...&&... |
| main.go:10:7:10:27 | ...&&... | main.go:10:2:10:2 | definition of z |
| main.go:10:7:10:27 | ...&&... | main.go:10:2:10:2 | SSA def(z) |
| main.go:10:12:10:12 | y | main.go:10:17:10:17 | y |
| main.go:10:17:10:27 | ...>=... | main.go:10:7:10:27 | ...&&... |
| main.go:11:14:11:14 | z | main.go:11:9:11:15 | type conversion |
| main.go:15:9:15:9 | 0 | main.go:15:2:15:4 | definition of acc |
| main.go:16:9:19:2 | capture variable acc | main.go:17:3:17:5 | acc |
| main.go:17:3:17:7 | definition of acc | main.go:18:10:18:12 | acc |
| main.go:17:3:17:7 | rhs of increment statement | main.go:17:3:17:7 | definition of acc |
| main.go:22:12:22:12 | argument corresponding to b | main.go:22:12:22:12 | definition of b |
| main.go:22:12:22:12 | definition of b | main.go:23:5:23:5 | b |
| main.go:22:20:22:20 | argument corresponding to x | main.go:22:20:22:20 | definition of x |
| main.go:22:20:22:20 | definition of x | main.go:24:10:24:10 | x |
| main.go:22:20:22:20 | definition of x | main.go:26:11:26:11 | x |
| main.go:15:9:15:9 | 0 | main.go:15:2:15:4 | SSA def(acc) |
| main.go:16:9:19:2 | SSA def(acc) | main.go:17:3:17:5 | acc |
| main.go:17:3:17:7 | SSA def(acc) | main.go:18:10:18:12 | acc |
| main.go:17:3:17:7 | rhs of increment statement | main.go:17:3:17:7 | SSA def(acc) |
| main.go:22:12:22:12 | SSA def(b) | main.go:23:5:23:5 | b |
| main.go:22:12:22:12 | argument corresponding to b | main.go:22:12:22:12 | SSA def(b) |
| main.go:22:20:22:20 | SSA def(x) | main.go:24:10:24:10 | x |
| main.go:22:20:22:20 | SSA def(x) | main.go:26:11:26:11 | x |
| main.go:22:20:22:20 | argument corresponding to x | main.go:22:20:22:20 | SSA def(x) |
| main.go:24:10:24:10 | x | main.go:24:10:24:19 | type assertion |
| main.go:26:2:26:2 | definition of n | main.go:27:11:27:11 | n |
| main.go:26:2:26:17 | ... := ...[0] | main.go:26:2:26:2 | definition of n |
| main.go:26:2:26:17 | ... := ...[1] | main.go:26:5:26:6 | definition of ok |
| main.go:26:5:26:6 | definition of ok | main.go:27:5:27:6 | ok |
| main.go:26:2:26:2 | SSA def(n) | main.go:27:11:27:11 | n |
| main.go:26:2:26:17 | ... := ...[0] | main.go:26:2:26:2 | SSA def(n) |
| main.go:26:2:26:17 | ... := ...[1] | main.go:26:5:26:6 | SSA def(ok) |
| main.go:26:5:26:6 | SSA def(ok) | main.go:27:5:27:6 | ok |
| main.go:26:11:26:11 | x | main.go:26:2:26:17 | ... := ...[0] |
| main.go:38:2:38:2 | definition of s | main.go:39:15:39:15 | s |
| main.go:38:7:38:20 | slice literal | main.go:38:2:38:2 | definition of s |
| main.go:38:7:38:20 | slice literal [postupdate] | main.go:38:2:38:2 | definition of s |
| main.go:39:2:39:3 | definition of s1 | main.go:40:18:40:19 | s1 |
| main.go:39:8:39:25 | call to append | main.go:39:2:39:3 | definition of s1 |
| main.go:38:2:38:2 | SSA def(s) | main.go:39:15:39:15 | s |
| main.go:38:7:38:20 | slice literal | main.go:38:2:38:2 | SSA def(s) |
| main.go:38:7:38:20 | slice literal [postupdate] | main.go:38:2:38:2 | SSA def(s) |
| main.go:39:2:39:3 | SSA def(s1) | main.go:40:18:40:19 | s1 |
| main.go:39:8:39:25 | call to append | main.go:39:2:39:3 | SSA def(s1) |
| main.go:39:15:39:15 | s | main.go:40:15:40:15 | s |
| main.go:39:15:39:15 | s [postupdate] | main.go:40:15:40:15 | s |
| main.go:40:2:40:3 | definition of s2 | main.go:43:9:43:10 | s2 |
| main.go:40:8:40:23 | call to append | main.go:40:2:40:3 | definition of s2 |
| main.go:40:2:40:3 | SSA def(s2) | main.go:43:9:43:10 | s2 |
| main.go:40:8:40:23 | call to append | main.go:40:2:40:3 | SSA def(s2) |
| main.go:40:15:40:15 | s | main.go:42:7:42:7 | s |
| main.go:40:15:40:15 | s [postupdate] | main.go:42:7:42:7 | s |
| main.go:41:2:41:3 | definition of s4 | main.go:42:10:42:11 | s4 |
| main.go:41:8:41:21 | call to make | main.go:41:2:41:3 | definition of s4 |
| main.go:46:13:46:14 | argument corresponding to xs | main.go:46:13:46:14 | definition of xs |
| main.go:46:13:46:14 | definition of xs | main.go:47:20:47:21 | xs |
| main.go:46:24:46:27 | definition of keys | main.go:46:24:46:27 | implicit read of keys |
| main.go:46:24:46:27 | definition of keys | main.go:49:3:49:6 | keys |
| main.go:46:24:46:27 | zero value for keys | main.go:46:24:46:27 | definition of keys |
| main.go:46:34:46:37 | definition of vals | main.go:46:34:46:37 | implicit read of vals |
| main.go:46:34:46:37 | definition of vals | main.go:48:3:48:6 | vals |
| main.go:46:34:46:37 | zero value for vals | main.go:46:34:46:37 | definition of vals |
| main.go:47:2:50:2 | range statement[0] | main.go:47:6:47:6 | definition of k |
| main.go:47:2:50:2 | range statement[1] | main.go:47:9:47:9 | definition of v |
| main.go:47:6:47:6 | definition of k | main.go:49:11:49:11 | k |
| main.go:47:9:47:9 | definition of v | main.go:48:11:48:11 | v |
| main.go:48:3:48:6 | definition of vals | main.go:46:34:46:37 | implicit read of vals |
| main.go:48:3:48:6 | definition of vals | main.go:48:3:48:6 | vals |
| main.go:48:3:48:11 | ... += ... | main.go:48:3:48:6 | definition of vals |
| main.go:49:3:49:6 | definition of keys | main.go:46:24:46:27 | implicit read of keys |
| main.go:49:3:49:6 | definition of keys | main.go:49:3:49:6 | keys |
| main.go:49:3:49:11 | ... += ... | main.go:49:3:49:6 | definition of keys |
| main.go:55:6:55:7 | definition of ch | main.go:56:2:56:3 | ch |
| main.go:55:6:55:7 | zero value for ch | main.go:55:6:55:7 | definition of ch |
| main.go:41:2:41:3 | SSA def(s4) | main.go:42:10:42:11 | s4 |
| main.go:41:8:41:21 | call to make | main.go:41:2:41:3 | SSA def(s4) |
| main.go:46:13:46:14 | SSA def(xs) | main.go:47:20:47:21 | xs |
| main.go:46:13:46:14 | argument corresponding to xs | main.go:46:13:46:14 | SSA def(xs) |
| main.go:46:24:46:27 | SSA def(keys) | main.go:46:24:46:27 | implicit read of keys |
| main.go:46:24:46:27 | SSA def(keys) | main.go:49:3:49:6 | keys |
| main.go:46:24:46:27 | zero value for keys | main.go:46:24:46:27 | SSA def(keys) |
| main.go:46:34:46:37 | SSA def(vals) | main.go:46:34:46:37 | implicit read of vals |
| main.go:46:34:46:37 | SSA def(vals) | main.go:48:3:48:6 | vals |
| main.go:46:34:46:37 | zero value for vals | main.go:46:34:46:37 | SSA def(vals) |
| main.go:47:2:50:2 | range statement[0] | main.go:47:6:47:6 | SSA def(k) |
| main.go:47:2:50:2 | range statement[1] | main.go:47:9:47:9 | SSA def(v) |
| main.go:47:6:47:6 | SSA def(k) | main.go:49:11:49:11 | k |
| main.go:47:9:47:9 | SSA def(v) | main.go:48:11:48:11 | v |
| main.go:48:3:48:6 | SSA def(vals) | main.go:46:34:46:37 | implicit read of vals |
| main.go:48:3:48:6 | SSA def(vals) | main.go:48:3:48:6 | vals |
| main.go:48:3:48:11 | ... += ... | main.go:48:3:48:6 | SSA def(vals) |
| main.go:49:3:49:6 | SSA def(keys) | main.go:46:24:46:27 | implicit read of keys |
| main.go:49:3:49:6 | SSA def(keys) | main.go:49:3:49:6 | keys |
| main.go:49:3:49:11 | ... += ... | main.go:49:3:49:6 | SSA def(keys) |
| main.go:55:6:55:7 | SSA def(ch) | main.go:56:2:56:3 | ch |
| main.go:55:6:55:7 | zero value for ch | main.go:55:6:55:7 | SSA def(ch) |
| main.go:56:2:56:3 | ch | main.go:57:4:57:5 | ch |
| main.go:56:2:56:3 | ch [postupdate] | main.go:57:4:57:5 | ch |
| main.go:61:2:61:2 | definition of x | main.go:64:11:64:11 | x |
| main.go:61:7:61:7 | 1 | main.go:61:2:61:2 | definition of x |
| main.go:62:2:62:2 | definition of y | main.go:64:14:64:14 | y |
| main.go:62:7:62:7 | 2 | main.go:62:2:62:2 | definition of y |
| main.go:63:2:63:2 | definition of z | main.go:64:17:64:17 | z |
| main.go:63:7:63:7 | 3 | main.go:63:2:63:2 | definition of z |
| main.go:64:2:64:2 | definition of a | main.go:66:9:66:9 | a |
| main.go:64:7:64:18 | call to min | main.go:64:2:64:2 | definition of a |
| main.go:61:2:61:2 | SSA def(x) | main.go:64:11:64:11 | x |
| main.go:61:7:61:7 | 1 | main.go:61:2:61:2 | SSA def(x) |
| main.go:62:2:62:2 | SSA def(y) | main.go:64:14:64:14 | y |
| main.go:62:7:62:7 | 2 | main.go:62:2:62:2 | SSA def(y) |
| main.go:63:2:63:2 | SSA def(z) | main.go:64:17:64:17 | z |
| main.go:63:7:63:7 | 3 | main.go:63:2:63:2 | SSA def(z) |
| main.go:64:2:64:2 | SSA def(a) | main.go:66:9:66:9 | a |
| main.go:64:7:64:18 | call to min | main.go:64:2:64:2 | SSA def(a) |
| main.go:64:11:64:11 | x | main.go:64:7:64:18 | call to min |
| main.go:64:11:64:11 | x | main.go:65:11:65:11 | x |
| main.go:64:14:64:14 | y | main.go:64:7:64:18 | call to min |
| main.go:64:14:64:14 | y | main.go:65:14:65:14 | y |
| main.go:64:17:64:17 | z | main.go:64:7:64:18 | call to min |
| main.go:64:17:64:17 | z | main.go:65:17:65:17 | z |
| main.go:65:2:65:2 | definition of b | main.go:66:12:66:12 | b |
| main.go:65:7:65:18 | call to max | main.go:65:2:65:2 | definition of b |
| main.go:65:2:65:2 | SSA def(b) | main.go:66:12:66:12 | b |
| main.go:65:7:65:18 | call to max | main.go:65:2:65:2 | SSA def(b) |
| main.go:65:11:65:11 | x | main.go:65:7:65:18 | call to max |
| main.go:65:14:65:14 | y | main.go:65:7:65:18 | call to max |
| main.go:65:17:65:17 | z | main.go:65:7:65:18 | call to max |
| strings.go:8:12:8:12 | argument corresponding to s | strings.go:8:12:8:12 | definition of s |
| strings.go:8:12:8:12 | definition of s | strings.go:9:24:9:24 | s |
| strings.go:9:2:9:3 | definition of s2 | strings.go:11:20:11:21 | s2 |
| strings.go:9:8:9:38 | call to Replace | strings.go:9:2:9:3 | definition of s2 |
| strings.go:8:12:8:12 | SSA def(s) | strings.go:9:24:9:24 | s |
| strings.go:8:12:8:12 | argument corresponding to s | strings.go:8:12:8:12 | SSA def(s) |
| strings.go:9:2:9:3 | SSA def(s2) | strings.go:11:20:11:21 | s2 |
| strings.go:9:8:9:38 | call to Replace | strings.go:9:2:9:3 | SSA def(s2) |
| strings.go:9:24:9:24 | s | strings.go:10:27:10:27 | s |
| strings.go:10:2:10:3 | definition of s3 | strings.go:11:24:11:25 | s3 |
| strings.go:10:8:10:42 | call to ReplaceAll | strings.go:10:2:10:3 | definition of s3 |
| strings.go:10:2:10:3 | SSA def(s3) | strings.go:11:24:11:25 | s3 |
| strings.go:10:8:10:42 | call to ReplaceAll | strings.go:10:2:10:3 | SSA def(s3) |
| strings.go:11:20:11:21 | s2 | strings.go:11:48:11:49 | s2 |
| strings.go:11:24:11:25 | s3 | strings.go:11:67:11:68 | s3 |
| url.go:8:12:8:12 | argument corresponding to b | url.go:8:12:8:12 | definition of b |
| url.go:8:12:8:12 | definition of b | url.go:11:5:11:5 | b |
| url.go:8:20:8:20 | argument corresponding to s | url.go:8:20:8:20 | definition of s |
| url.go:8:20:8:20 | definition of s | url.go:12:46:12:46 | s |
| url.go:8:20:8:20 | definition of s | url.go:14:48:14:48 | s |
| url.go:12:3:12:5 | definition of res | url.go:19:9:19:11 | res |
| url.go:12:3:12:48 | ... = ...[0] | url.go:12:3:12:5 | definition of res |
| url.go:12:3:12:48 | ... = ...[1] | url.go:12:8:12:10 | definition of err |
| url.go:12:8:12:10 | definition of err | url.go:16:5:16:7 | err |
| url.go:14:3:14:5 | definition of res | url.go:19:9:19:11 | res |
| url.go:14:3:14:50 | ... = ...[0] | url.go:14:3:14:5 | definition of res |
| url.go:14:3:14:50 | ... = ...[1] | url.go:14:8:14:10 | definition of err |
| url.go:14:8:14:10 | definition of err | url.go:16:5:16:7 | err |
| url.go:22:12:22:12 | argument corresponding to i | url.go:22:12:22:12 | definition of i |
| url.go:22:12:22:12 | definition of i | url.go:24:5:24:5 | i |
| url.go:22:19:22:19 | argument corresponding to s | url.go:22:19:22:19 | definition of s |
| url.go:22:19:22:19 | definition of s | url.go:23:20:23:20 | s |
| url.go:23:2:23:2 | definition of u | url.go:25:10:25:10 | u |
| url.go:23:2:23:21 | ... := ...[0] | url.go:23:2:23:2 | definition of u |
| url.go:8:12:8:12 | SSA def(b) | url.go:11:5:11:5 | b |
| url.go:8:12:8:12 | argument corresponding to b | url.go:8:12:8:12 | SSA def(b) |
| url.go:8:20:8:20 | SSA def(s) | url.go:12:46:12:46 | s |
| url.go:8:20:8:20 | SSA def(s) | url.go:14:48:14:48 | s |
| url.go:8:20:8:20 | argument corresponding to s | url.go:8:20:8:20 | SSA def(s) |
| url.go:12:3:12:5 | SSA def(res) | url.go:19:9:19:11 | res |
| url.go:12:3:12:48 | ... = ...[0] | url.go:12:3:12:5 | SSA def(res) |
| url.go:12:3:12:48 | ... = ...[1] | url.go:12:8:12:10 | SSA def(err) |
| url.go:12:8:12:10 | SSA def(err) | url.go:16:5:16:7 | err |
| url.go:14:3:14:5 | SSA def(res) | url.go:19:9:19:11 | res |
| url.go:14:3:14:50 | ... = ...[0] | url.go:14:3:14:5 | SSA def(res) |
| url.go:14:3:14:50 | ... = ...[1] | url.go:14:8:14:10 | SSA def(err) |
| url.go:14:8:14:10 | SSA def(err) | url.go:16:5:16:7 | err |
| url.go:22:12:22:12 | SSA def(i) | url.go:24:5:24:5 | i |
| url.go:22:12:22:12 | argument corresponding to i | url.go:22:12:22:12 | SSA def(i) |
| url.go:22:19:22:19 | SSA def(s) | url.go:23:20:23:20 | s |
| url.go:22:19:22:19 | argument corresponding to s | url.go:22:19:22:19 | SSA def(s) |
| url.go:23:2:23:2 | SSA def(u) | url.go:25:10:25:10 | u |
| url.go:23:2:23:21 | ... := ...[0] | url.go:23:2:23:2 | SSA def(u) |
| url.go:23:20:23:20 | s | url.go:27:29:27:29 | s |
| url.go:27:2:27:2 | definition of u | url.go:28:14:28:14 | u |
| url.go:27:2:27:30 | ... = ...[0] | url.go:27:2:27:2 | definition of u |
| url.go:27:2:27:2 | SSA def(u) | url.go:28:14:28:14 | u |
| url.go:27:2:27:30 | ... = ...[0] | url.go:27:2:27:2 | SSA def(u) |
| url.go:28:14:28:14 | u | url.go:29:14:29:14 | u |
| url.go:28:14:28:14 | u [postupdate] | url.go:29:14:29:14 | u |
| url.go:29:14:29:14 | u | url.go:30:11:30:11 | u |
| url.go:29:14:29:14 | u [postupdate] | url.go:30:11:30:11 | u |
| url.go:30:2:30:3 | definition of bs | url.go:31:14:31:15 | bs |
| url.go:30:2:30:27 | ... := ...[0] | url.go:30:2:30:3 | definition of bs |
| url.go:30:2:30:3 | SSA def(bs) | url.go:31:14:31:15 | bs |
| url.go:30:2:30:27 | ... := ...[0] | url.go:30:2:30:3 | SSA def(bs) |
| url.go:30:11:30:11 | u | url.go:32:9:32:9 | u |
| url.go:30:11:30:11 | u [postupdate] | url.go:32:9:32:9 | u |
| url.go:32:2:32:2 | definition of u | url.go:33:14:33:14 | u |
| url.go:32:2:32:23 | ... = ...[0] | url.go:32:2:32:2 | definition of u |
| url.go:32:2:32:2 | SSA def(u) | url.go:33:14:33:14 | u |
| url.go:32:2:32:23 | ... = ...[0] | url.go:32:2:32:2 | SSA def(u) |
| url.go:33:14:33:14 | u | url.go:34:14:34:14 | u |
| url.go:33:14:33:14 | u [postupdate] | url.go:34:14:34:14 | u |
| url.go:34:14:34:14 | u | url.go:35:14:35:14 | u |
| url.go:34:14:34:14 | u [postupdate] | url.go:35:14:35:14 | u |
| url.go:35:14:35:14 | u | url.go:36:6:36:6 | u |
| url.go:35:14:35:14 | u [postupdate] | url.go:36:6:36:6 | u |
| url.go:36:2:36:2 | definition of u | url.go:37:9:37:9 | u |
| url.go:36:2:36:2 | SSA def(u) | url.go:37:9:37:9 | u |
| url.go:36:6:36:6 | u | url.go:36:25:36:25 | u |
| url.go:36:6:36:6 | u [postupdate] | url.go:36:25:36:25 | u |
| url.go:36:6:36:26 | call to ResolveReference | url.go:36:2:36:2 | definition of u |
| url.go:42:2:42:3 | definition of ui | url.go:43:11:43:12 | ui |
| url.go:42:7:42:38 | call to UserPassword | url.go:42:2:42:3 | definition of ui |
| url.go:43:2:43:3 | definition of pw | url.go:44:14:44:15 | pw |
| url.go:43:2:43:23 | ... := ...[0] | url.go:43:2:43:3 | definition of pw |
| url.go:36:6:36:26 | call to ResolveReference | url.go:36:2:36:2 | SSA def(u) |
| url.go:42:2:42:3 | SSA def(ui) | url.go:43:11:43:12 | ui |
| url.go:42:7:42:38 | call to UserPassword | url.go:42:2:42:3 | SSA def(ui) |
| url.go:43:2:43:3 | SSA def(pw) | url.go:44:14:44:15 | pw |
| url.go:43:2:43:23 | ... := ...[0] | url.go:43:2:43:3 | SSA def(pw) |
| url.go:43:11:43:12 | ui | url.go:45:14:45:15 | ui |
| url.go:43:11:43:12 | ui [postupdate] | url.go:45:14:45:15 | ui |
| url.go:45:14:45:15 | ui | url.go:46:9:46:10 | ui |
| url.go:45:14:45:15 | ui [postupdate] | url.go:46:9:46:10 | ui |
| url.go:49:12:49:12 | argument corresponding to q | url.go:49:12:49:12 | definition of q |
| url.go:49:12:49:12 | definition of q | url.go:50:25:50:25 | q |
| url.go:50:2:50:2 | definition of v | url.go:51:14:51:14 | v |
| url.go:50:2:50:26 | ... := ...[0] | url.go:50:2:50:2 | definition of v |
| url.go:49:12:49:12 | SSA def(q) | url.go:50:25:50:25 | q |
| url.go:49:12:49:12 | argument corresponding to q | url.go:49:12:49:12 | SSA def(q) |
| url.go:50:2:50:2 | SSA def(v) | url.go:51:14:51:14 | v |
| url.go:50:2:50:26 | ... := ...[0] | url.go:50:2:50:2 | SSA def(v) |
| url.go:51:14:51:14 | v | url.go:52:14:52:14 | v |
| url.go:51:14:51:14 | v [postupdate] | url.go:52:14:52:14 | v |
| url.go:52:14:52:14 | v | url.go:53:9:53:9 | v |
| url.go:52:14:52:14 | v [postupdate] | url.go:53:9:53:9 | v |
| url.go:56:12:56:12 | argument corresponding to q | url.go:56:12:56:12 | definition of q |
| url.go:56:12:56:12 | definition of q | url.go:57:29:57:29 | q |
| url.go:57:2:57:8 | definition of joined1 | url.go:58:38:58:44 | joined1 |
| url.go:57:2:57:39 | ... := ...[0] | url.go:57:2:57:8 | definition of joined1 |
| url.go:58:2:58:8 | definition of joined2 | url.go:59:24:59:30 | joined2 |
| url.go:58:2:58:45 | ... := ...[0] | url.go:58:2:58:8 | definition of joined2 |
| url.go:59:2:59:6 | definition of asUrl | url.go:60:15:60:19 | asUrl |
| url.go:59:2:59:31 | ... := ...[0] | url.go:59:2:59:6 | definition of asUrl |
| url.go:60:2:60:10 | definition of joinedUrl | url.go:61:9:61:17 | joinedUrl |
| url.go:60:15:60:37 | call to JoinPath | url.go:60:2:60:10 | definition of joinedUrl |
| url.go:64:13:64:13 | argument corresponding to q | url.go:64:13:64:13 | definition of q |
| url.go:64:13:64:13 | definition of q | url.go:66:27:66:27 | q |
| url.go:65:2:65:9 | definition of cleanUrl | url.go:66:9:66:16 | cleanUrl |
| url.go:65:2:65:48 | ... := ...[0] | url.go:65:2:65:9 | definition of cleanUrl |
| url.go:56:12:56:12 | SSA def(q) | url.go:57:29:57:29 | q |
| url.go:56:12:56:12 | argument corresponding to q | url.go:56:12:56:12 | SSA def(q) |
| url.go:57:2:57:8 | SSA def(joined1) | url.go:58:38:58:44 | joined1 |
| url.go:57:2:57:39 | ... := ...[0] | url.go:57:2:57:8 | SSA def(joined1) |
| url.go:58:2:58:8 | SSA def(joined2) | url.go:59:24:59:30 | joined2 |
| url.go:58:2:58:45 | ... := ...[0] | url.go:58:2:58:8 | SSA def(joined2) |
| url.go:59:2:59:6 | SSA def(asUrl) | url.go:60:15:60:19 | asUrl |
| url.go:59:2:59:31 | ... := ...[0] | url.go:59:2:59:6 | SSA def(asUrl) |
| url.go:60:2:60:10 | SSA def(joinedUrl) | url.go:61:9:61:17 | joinedUrl |
| url.go:60:15:60:37 | call to JoinPath | url.go:60:2:60:10 | SSA def(joinedUrl) |
| url.go:64:13:64:13 | SSA def(q) | url.go:66:27:66:27 | q |
| url.go:64:13:64:13 | argument corresponding to q | url.go:64:13:64:13 | SSA def(q) |
| url.go:65:2:65:9 | SSA def(cleanUrl) | url.go:66:9:66:16 | cleanUrl |
| url.go:65:2:65:48 | ... := ...[0] | url.go:65:2:65:9 | SSA def(cleanUrl) |

View File

@@ -25,15 +25,15 @@
| result | main.go:53:2:53:22 | call to op2 | main.go:53:2:53:22 | call to op2 |
| result | main.go:53:14:53:21 | call to bump | main.go:53:14:53:21 | call to bump |
| result | tst2.go:10:9:10:26 | call to NewEncoder | tst2.go:10:9:10:26 | call to NewEncoder |
| result | tst2.go:10:9:10:39 | call to Encode | tst2.go:10:2:10:4 | definition of err |
| result | tst.go:9:17:9:33 | call to new | tst.go:9:2:9:12 | definition of bytesBuffer |
| result | tst2.go:10:9:10:39 | call to Encode | tst2.go:10:2:10:4 | SSA def(err) |
| result | tst.go:9:17:9:33 | call to new | tst.go:9:2:9:12 | SSA def(bytesBuffer) |
| result 0 | main.go:51:2:51:14 | call to op | main.go:51:2:51:14 | call to op |
| result 0 | main.go:53:2:53:22 | call to op2 | main.go:53:2:53:22 | call to op2 |
| result 0 | main.go:53:14:53:21 | call to bump | main.go:53:14:53:21 | call to bump |
| result 0 | main.go:54:10:54:15 | call to test | main.go:54:2:54:2 | definition of x |
| result 0 | main.go:56:9:56:15 | call to test2 | main.go:56:2:56:2 | definition of x |
| result 0 | main.go:54:10:54:15 | call to test | main.go:54:2:54:2 | SSA def(x) |
| result 0 | main.go:56:9:56:15 | call to test2 | main.go:56:2:56:2 | SSA def(x) |
| result 0 | tst2.go:10:9:10:26 | call to NewEncoder | tst2.go:10:9:10:26 | call to NewEncoder |
| result 0 | tst2.go:10:9:10:39 | call to Encode | tst2.go:10:2:10:4 | definition of err |
| result 0 | tst.go:9:17:9:33 | call to new | tst.go:9:2:9:12 | definition of bytesBuffer |
| result 1 | main.go:54:10:54:15 | call to test | main.go:54:5:54:5 | definition of y |
| result 1 | main.go:56:9:56:15 | call to test2 | main.go:56:5:56:5 | definition of y |
| result 0 | tst2.go:10:9:10:39 | call to Encode | tst2.go:10:2:10:4 | SSA def(err) |
| result 0 | tst.go:9:17:9:33 | call to new | tst.go:9:2:9:12 | SSA def(bytesBuffer) |
| result 1 | main.go:54:10:54:15 | call to test | main.go:54:5:54:5 | SSA def(y) |
| result 1 | main.go:56:9:56:15 | call to test2 | main.go:56:5:56:5 | SSA def(y) |

View File

@@ -1,14 +1,14 @@
| parameter 0 | main.go:5:1:11:1 | function declaration | main.go:5:9:5:10 | definition of op |
| parameter 0 | main.go:13:1:20:1 | function declaration | main.go:13:10:13:11 | definition of op |
| parameter 0 | main.go:40:1:48:1 | function declaration | main.go:40:12:40:12 | definition of b |
| parameter 0 | reset.go:8:1:16:1 | function declaration | reset.go:8:27:8:27 | definition of r |
| parameter 0 | tst2.go:8:1:12:1 | function declaration | tst2.go:8:12:8:15 | definition of data |
| parameter 0 | tst.go:8:1:11:1 | function declaration | tst.go:8:12:8:17 | definition of reader |
| parameter 0 | main.go:5:1:11:1 | function declaration | main.go:5:9:5:10 | SSA def(op) |
| parameter 0 | main.go:13:1:20:1 | function declaration | main.go:13:10:13:11 | SSA def(op) |
| parameter 0 | main.go:40:1:48:1 | function declaration | main.go:40:12:40:12 | SSA def(b) |
| parameter 0 | reset.go:8:1:16:1 | function declaration | reset.go:8:27:8:27 | SSA def(r) |
| parameter 0 | tst2.go:8:1:12:1 | function declaration | tst2.go:8:12:8:15 | SSA def(data) |
| parameter 0 | tst.go:8:1:11:1 | function declaration | tst.go:8:12:8:17 | SSA def(reader) |
| parameter 0 | tst.go:13:1:13:25 | function declaration | tst.go:13:12:13:13 | initialization of xs |
| parameter 0 | tst.go:15:1:19:1 | function declaration | tst.go:15:12:15:12 | definition of x |
| parameter 1 | main.go:5:1:11:1 | function declaration | main.go:5:20:5:20 | definition of x |
| parameter 1 | main.go:13:1:20:1 | function declaration | main.go:13:21:13:21 | definition of x |
| parameter 1 | tst.go:15:1:19:1 | function declaration | tst.go:15:15:15:15 | definition of y |
| parameter 2 | main.go:5:1:11:1 | function declaration | main.go:5:27:5:27 | definition of y |
| parameter 2 | main.go:13:1:20:1 | function declaration | main.go:13:28:13:28 | definition of y |
| receiver | main.go:26:1:29:1 | function declaration | main.go:26:7:26:7 | definition of c |
| parameter 0 | tst.go:15:1:19:1 | function declaration | tst.go:15:12:15:12 | SSA def(x) |
| parameter 1 | main.go:5:1:11:1 | function declaration | main.go:5:20:5:20 | SSA def(x) |
| parameter 1 | main.go:13:1:20:1 | function declaration | main.go:13:21:13:21 | SSA def(x) |
| parameter 1 | tst.go:15:1:19:1 | function declaration | tst.go:15:15:15:15 | SSA def(y) |
| parameter 2 | main.go:5:1:11:1 | function declaration | main.go:5:27:5:27 | SSA def(y) |
| parameter 2 | main.go:13:1:20:1 | function declaration | main.go:13:28:13:28 | SSA def(y) |
| receiver | main.go:26:1:29:1 | function declaration | main.go:26:7:26:7 | SSA def(c) |

View File

@@ -1,18 +1,18 @@
| main.go:6:2:6:5 | 1 | main.go:14:7:14:7 | 1 |
| main.go:10:2:10:2 | definition of x | main.go:10:7:10:7 | 0 |
| main.go:10:2:10:2 | SSA def(x) | main.go:10:7:10:7 | 0 |
| main.go:10:7:10:7 | 0 | main.go:10:7:10:7 | 0 |
| main.go:11:6:11:6 | definition of y | main.go:10:7:10:7 | 0 |
| main.go:11:6:11:6 | SSA def(y) | main.go:10:7:10:7 | 0 |
| main.go:11:6:11:6 | zero value for y | main.go:10:7:10:7 | 0 |
| main.go:12:2:12:18 | call to Println | main.go:12:2:12:18 | call to Println |
| main.go:12:14:12:14 | x | main.go:10:7:10:7 | 0 |
| main.go:12:17:12:17 | y | main.go:10:7:10:7 | 0 |
| main.go:14:2:14:2 | definition of z | main.go:14:7:14:7 | 1 |
| main.go:14:2:14:2 | SSA def(z) | main.go:14:7:14:7 | 1 |
| main.go:14:7:14:7 | 1 | main.go:14:7:14:7 | 1 |
| main.go:15:2:15:9 | call to bump | main.go:15:2:15:9 | call to bump |
| main.go:16:2:16:21 | call to Println | main.go:16:2:16:21 | call to Println |
| main.go:16:14:16:14 | x | main.go:10:7:10:7 | 0 |
| main.go:16:17:16:17 | y | main.go:10:7:10:7 | 0 |
| main.go:18:2:18:3 | definition of ss | main.go:18:8:18:24 | call to make |
| main.go:18:2:18:3 | SSA def(ss) | main.go:18:8:18:24 | call to make |
| main.go:18:8:18:24 | call to make | main.go:18:8:18:24 | call to make |
| main.go:18:23:18:23 | 3 | main.go:18:23:18:23 | 3 |
| main.go:19:5:19:5 | 2 | main.go:19:5:19:5 | 2 |
@@ -20,22 +20,20 @@
| main.go:20:2:20:16 | call to Println | main.go:20:2:20:16 | call to Println |
| main.go:23:14:23:16 | implicit read of res | main.go:24:8:24:8 | 4 |
| main.go:23:14:23:16 | zero value for res | main.go:10:7:10:7 | 0 |
| main.go:24:2:24:4 | definition of res | main.go:24:8:24:8 | 4 |
| main.go:24:2:24:4 | SSA def(res) | main.go:24:8:24:8 | 4 |
| main.go:24:8:24:8 | 4 | main.go:24:8:24:8 | 4 |
| main.go:28:15:28:17 | implicit read of res | main.go:30:9:30:9 | 6 |
| main.go:28:15:28:17 | zero value for res | main.go:10:7:10:7 | 0 |
| main.go:29:8:29:8 | 5 | main.go:29:8:29:8 | 5 |
| main.go:30:9:30:9 | 6 | main.go:30:9:30:9 | 6 |
| main.go:30:9:30:9 | definition of res | main.go:30:9:30:9 | 6 |
| main.go:33:15:33:17 | definition of res | main.go:10:7:10:7 | 0 |
| main.go:30:9:30:9 | SSA def(res) | main.go:30:9:30:9 | 6 |
| main.go:33:15:33:17 | zero value for res | main.go:10:7:10:7 | 0 |
| main.go:34:2:34:4 | definition of res | main.go:34:8:34:8 | 7 |
| main.go:34:8:34:8 | 7 | main.go:34:8:34:8 | 7 |
| main.go:35:8:37:4 | function call | main.go:35:8:37:4 | function call |
| main.go:36:3:36:5 | definition of res | main.go:36:9:36:9 | 8 |
| main.go:36:3:36:5 | SSA def(res) | main.go:36:9:36:9 | 8 |
| main.go:36:9:36:9 | 8 | main.go:36:9:36:9 | 8 |
| main.go:38:9:38:9 | 9 | main.go:38:9:38:9 | 9 |
| main.go:38:9:38:9 | definition of res | main.go:38:9:38:9 | 9 |
| main.go:38:9:38:9 | SSA def(res) | main.go:38:9:38:9 | 9 |
| regressions.go:5:11:5:31 | call to Sizeof | regressions.go:5:11:5:31 | call to Sizeof |
| regressions.go:7:11:7:15 | false | regressions.go:7:11:7:15 | false |
| regressions.go:9:11:9:12 | !... | regressions.go:11:11:11:14 | true |

View File

@@ -2,3 +2,5 @@
| main.go:7:19:7:23 | ...+... | + | main.go:7:19:7:19 | y | main.go:7:23:7:23 | z |
| main.go:10:14:10:18 | ...+... | + | main.go:10:14:10:14 | x | main.go:10:18:10:18 | y |
| main.go:17:2:17:13 | ... += ... | + | main.go:17:2:17:6 | index expression | main.go:17:11:17:13 | "!" |
| resultParameters.go:4:5:4:17 | ...==... | == | resultParameters.go:4:5:4:12 | selector | resultParameters.go:4:17:4:17 | 0 |
| resultParameters.go:23:5:23:17 | ...==... | == | resultParameters.go:23:5:23:12 | selector | resultParameters.go:23:17:23:17 | 1 |

View File

@@ -0,0 +1,8 @@
| main.go:21:9:21:10 | 23 | Result node with index 0 |
| main.go:21:13:21:14 | 42 | Result node with index 1 |
| resultParameters.go:5:10:5:10 | 0 | Result node with index 0 |
| resultParameters.go:9:10:9:10 | 1 | Result node with index 0 |
| resultParameters.go:11:10:11:10 | 2 | Result node with index 0 |
| resultParameters.go:13:9:13:9 | 3 | Result node with index 0 |
| resultParameters.go:16:26:16:26 | implicit read of r | Result node with index 0 |
| resultParameters.go:21:38:21:38 | implicit read of r | Result node with index 0 |

View File

@@ -0,0 +1,9 @@
/**
* @kind problem
* @id result-node
*/
import go
from DataFlow::ResultNode r
select r, "Result node with index " + r.getIndex()

View File

@@ -0,0 +1,2 @@
query: ResultNode.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -18,5 +18,5 @@ func f() {
}
func test() (int, int) {
return 23, 42
return 23, 42 // $ Alert[result-node]
}

View File

@@ -0,0 +1,27 @@
package main
func multipleReturns(selector int) int {
if selector == 0 {
return 0 // $ Alert[result-node]
}
switch selector {
case 1:
return 1 // $ Alert[result-node]
case 2:
return 2 // $ Alert[result-node]
}
return 3 // $ Alert[result-node]
}
func resultParameter1() (r int) { // $ Alert[result-node] // implicit reads of result parameters are located at the result parameter declaration
r = 0
return
}
func resultParameter2(selector int) (r int) { // $ Alert[result-node] // implicit reads of result parameters are located at the result parameter declaration
r = 0
if selector == 1 {
return 1
}
return
}

View File

@@ -1,132 +1,132 @@
| main.go:22:2:22:6 | definition of outer | main.go:25:7:25:11 | outer |
| main.go:22:11:24:2 | struct literal | main.go:22:2:22:6 | definition of outer |
| main.go:22:11:24:2 | struct literal [postupdate] | main.go:22:2:22:6 | definition of outer |
| main.go:22:2:22:6 | SSA def(outer) | main.go:25:7:25:11 | outer |
| main.go:22:11:24:2 | struct literal | main.go:22:2:22:6 | SSA def(outer) |
| main.go:22:11:24:2 | struct literal [postupdate] | main.go:22:2:22:6 | SSA def(outer) |
| main.go:25:7:25:11 | outer | main.go:26:7:26:11 | outer |
| main.go:26:7:26:11 | outer | main.go:27:7:27:11 | outer |
| main.go:27:7:27:11 | outer | main.go:28:7:28:11 | outer |
| main.go:30:2:30:7 | definition of outerp | main.go:33:7:33:12 | outerp |
| main.go:30:12:32:2 | &... | main.go:30:2:30:7 | definition of outerp |
| main.go:30:12:32:2 | &... [postupdate] | main.go:30:2:30:7 | definition of outerp |
| main.go:30:2:30:7 | SSA def(outerp) | main.go:33:7:33:12 | outerp |
| main.go:30:12:32:2 | &... | main.go:30:2:30:7 | SSA def(outerp) |
| main.go:30:12:32:2 | &... [postupdate] | main.go:30:2:30:7 | SSA def(outerp) |
| main.go:33:7:33:12 | outerp | main.go:34:7:34:12 | outerp |
| main.go:33:7:33:12 | outerp [postupdate] | main.go:34:7:34:12 | outerp |
| main.go:34:7:34:12 | outerp | main.go:35:7:35:12 | outerp |
| main.go:34:7:34:12 | outerp [postupdate] | main.go:35:7:35:12 | outerp |
| main.go:35:7:35:12 | outerp | main.go:36:7:36:12 | outerp |
| main.go:35:7:35:12 | outerp [postupdate] | main.go:36:7:36:12 | outerp |
| main.go:40:2:40:6 | definition of outer | main.go:41:7:41:11 | outer |
| main.go:40:11:40:40 | struct literal | main.go:40:2:40:6 | definition of outer |
| main.go:40:11:40:40 | struct literal [postupdate] | main.go:40:2:40:6 | definition of outer |
| main.go:40:2:40:6 | SSA def(outer) | main.go:41:7:41:11 | outer |
| main.go:40:11:40:40 | struct literal | main.go:40:2:40:6 | SSA def(outer) |
| main.go:40:11:40:40 | struct literal [postupdate] | main.go:40:2:40:6 | SSA def(outer) |
| main.go:41:7:41:11 | outer | main.go:42:7:42:11 | outer |
| main.go:42:7:42:11 | outer | main.go:43:7:43:11 | outer |
| main.go:43:7:43:11 | outer | main.go:44:7:44:11 | outer |
| main.go:46:2:46:7 | definition of outerp | main.go:47:7:47:12 | outerp |
| main.go:46:12:46:42 | &... | main.go:46:2:46:7 | definition of outerp |
| main.go:46:12:46:42 | &... [postupdate] | main.go:46:2:46:7 | definition of outerp |
| main.go:46:2:46:7 | SSA def(outerp) | main.go:47:7:47:12 | outerp |
| main.go:46:12:46:42 | &... | main.go:46:2:46:7 | SSA def(outerp) |
| main.go:46:12:46:42 | &... [postupdate] | main.go:46:2:46:7 | SSA def(outerp) |
| main.go:47:7:47:12 | outerp | main.go:48:7:48:12 | outerp |
| main.go:47:7:47:12 | outerp [postupdate] | main.go:48:7:48:12 | outerp |
| main.go:48:7:48:12 | outerp | main.go:49:7:49:12 | outerp |
| main.go:48:7:48:12 | outerp [postupdate] | main.go:49:7:49:12 | outerp |
| main.go:49:7:49:12 | outerp | main.go:50:7:50:12 | outerp |
| main.go:49:7:49:12 | outerp [postupdate] | main.go:50:7:50:12 | outerp |
| main.go:54:2:54:6 | definition of inner | main.go:55:19:55:23 | inner |
| main.go:54:11:54:25 | struct literal | main.go:54:2:54:6 | definition of inner |
| main.go:54:11:54:25 | struct literal [postupdate] | main.go:54:2:54:6 | definition of inner |
| main.go:55:2:55:7 | definition of middle | main.go:56:17:56:22 | middle |
| main.go:55:12:55:24 | struct literal | main.go:55:2:55:7 | definition of middle |
| main.go:55:12:55:24 | struct literal [postupdate] | main.go:55:2:55:7 | definition of middle |
| main.go:56:2:56:6 | definition of outer | main.go:57:7:57:11 | outer |
| main.go:56:11:56:23 | struct literal | main.go:56:2:56:6 | definition of outer |
| main.go:56:11:56:23 | struct literal [postupdate] | main.go:56:2:56:6 | definition of outer |
| main.go:54:2:54:6 | SSA def(inner) | main.go:55:19:55:23 | inner |
| main.go:54:11:54:25 | struct literal | main.go:54:2:54:6 | SSA def(inner) |
| main.go:54:11:54:25 | struct literal [postupdate] | main.go:54:2:54:6 | SSA def(inner) |
| main.go:55:2:55:7 | SSA def(middle) | main.go:56:17:56:22 | middle |
| main.go:55:12:55:24 | struct literal | main.go:55:2:55:7 | SSA def(middle) |
| main.go:55:12:55:24 | struct literal [postupdate] | main.go:55:2:55:7 | SSA def(middle) |
| main.go:56:2:56:6 | SSA def(outer) | main.go:57:7:57:11 | outer |
| main.go:56:11:56:23 | struct literal | main.go:56:2:56:6 | SSA def(outer) |
| main.go:56:11:56:23 | struct literal [postupdate] | main.go:56:2:56:6 | SSA def(outer) |
| main.go:57:7:57:11 | outer | main.go:58:7:58:11 | outer |
| main.go:58:7:58:11 | outer | main.go:59:7:59:11 | outer |
| main.go:59:7:59:11 | outer | main.go:60:7:60:11 | outer |
| main.go:62:2:62:7 | definition of innerp | main.go:63:20:63:25 | innerp |
| main.go:62:12:62:26 | struct literal | main.go:62:2:62:7 | definition of innerp |
| main.go:62:12:62:26 | struct literal [postupdate] | main.go:62:2:62:7 | definition of innerp |
| main.go:63:2:63:8 | definition of middlep | main.go:64:18:64:24 | middlep |
| main.go:63:13:63:26 | struct literal | main.go:63:2:63:8 | definition of middlep |
| main.go:63:13:63:26 | struct literal [postupdate] | main.go:63:2:63:8 | definition of middlep |
| main.go:64:2:64:7 | definition of outerp | main.go:65:7:65:12 | outerp |
| main.go:64:12:64:25 | struct literal | main.go:64:2:64:7 | definition of outerp |
| main.go:64:12:64:25 | struct literal [postupdate] | main.go:64:2:64:7 | definition of outerp |
| main.go:62:2:62:7 | SSA def(innerp) | main.go:63:20:63:25 | innerp |
| main.go:62:12:62:26 | struct literal | main.go:62:2:62:7 | SSA def(innerp) |
| main.go:62:12:62:26 | struct literal [postupdate] | main.go:62:2:62:7 | SSA def(innerp) |
| main.go:63:2:63:8 | SSA def(middlep) | main.go:64:18:64:24 | middlep |
| main.go:63:13:63:26 | struct literal | main.go:63:2:63:8 | SSA def(middlep) |
| main.go:63:13:63:26 | struct literal [postupdate] | main.go:63:2:63:8 | SSA def(middlep) |
| main.go:64:2:64:7 | SSA def(outerp) | main.go:65:7:65:12 | outerp |
| main.go:64:12:64:25 | struct literal | main.go:64:2:64:7 | SSA def(outerp) |
| main.go:64:12:64:25 | struct literal [postupdate] | main.go:64:2:64:7 | SSA def(outerp) |
| main.go:65:7:65:12 | outerp | main.go:66:7:66:12 | outerp |
| main.go:66:7:66:12 | outerp | main.go:67:7:67:12 | outerp |
| main.go:67:7:67:12 | outerp | main.go:68:7:68:12 | outerp |
| main.go:72:2:72:6 | definition of inner | main.go:73:26:73:30 | inner |
| main.go:72:11:72:25 | struct literal | main.go:72:2:72:6 | definition of inner |
| main.go:72:11:72:25 | struct literal [postupdate] | main.go:72:2:72:6 | definition of inner |
| main.go:73:2:73:7 | definition of middle | main.go:74:25:74:30 | middle |
| main.go:73:12:73:31 | struct literal | main.go:73:2:73:7 | definition of middle |
| main.go:73:12:73:31 | struct literal [postupdate] | main.go:73:2:73:7 | definition of middle |
| main.go:74:2:74:6 | definition of outer | main.go:75:7:75:11 | outer |
| main.go:74:11:74:31 | struct literal | main.go:74:2:74:6 | definition of outer |
| main.go:74:11:74:31 | struct literal [postupdate] | main.go:74:2:74:6 | definition of outer |
| main.go:72:2:72:6 | SSA def(inner) | main.go:73:26:73:30 | inner |
| main.go:72:11:72:25 | struct literal | main.go:72:2:72:6 | SSA def(inner) |
| main.go:72:11:72:25 | struct literal [postupdate] | main.go:72:2:72:6 | SSA def(inner) |
| main.go:73:2:73:7 | SSA def(middle) | main.go:74:25:74:30 | middle |
| main.go:73:12:73:31 | struct literal | main.go:73:2:73:7 | SSA def(middle) |
| main.go:73:12:73:31 | struct literal [postupdate] | main.go:73:2:73:7 | SSA def(middle) |
| main.go:74:2:74:6 | SSA def(outer) | main.go:75:7:75:11 | outer |
| main.go:74:11:74:31 | struct literal | main.go:74:2:74:6 | SSA def(outer) |
| main.go:74:11:74:31 | struct literal [postupdate] | main.go:74:2:74:6 | SSA def(outer) |
| main.go:75:7:75:11 | outer | main.go:76:7:76:11 | outer |
| main.go:76:7:76:11 | outer | main.go:77:7:77:11 | outer |
| main.go:77:7:77:11 | outer | main.go:78:7:78:11 | outer |
| main.go:80:2:80:7 | definition of innerp | main.go:81:27:81:32 | innerp |
| main.go:80:12:80:26 | struct literal | main.go:80:2:80:7 | definition of innerp |
| main.go:80:12:80:26 | struct literal [postupdate] | main.go:80:2:80:7 | definition of innerp |
| main.go:81:2:81:8 | definition of middlep | main.go:82:26:82:32 | middlep |
| main.go:81:13:81:33 | struct literal | main.go:81:2:81:8 | definition of middlep |
| main.go:81:13:81:33 | struct literal [postupdate] | main.go:81:2:81:8 | definition of middlep |
| main.go:82:2:82:7 | definition of outerp | main.go:83:7:83:12 | outerp |
| main.go:82:12:82:33 | struct literal | main.go:82:2:82:7 | definition of outerp |
| main.go:82:12:82:33 | struct literal [postupdate] | main.go:82:2:82:7 | definition of outerp |
| main.go:80:2:80:7 | SSA def(innerp) | main.go:81:27:81:32 | innerp |
| main.go:80:12:80:26 | struct literal | main.go:80:2:80:7 | SSA def(innerp) |
| main.go:80:12:80:26 | struct literal [postupdate] | main.go:80:2:80:7 | SSA def(innerp) |
| main.go:81:2:81:8 | SSA def(middlep) | main.go:82:26:82:32 | middlep |
| main.go:81:13:81:33 | struct literal | main.go:81:2:81:8 | SSA def(middlep) |
| main.go:81:13:81:33 | struct literal [postupdate] | main.go:81:2:81:8 | SSA def(middlep) |
| main.go:82:2:82:7 | SSA def(outerp) | main.go:83:7:83:12 | outerp |
| main.go:82:12:82:33 | struct literal | main.go:82:2:82:7 | SSA def(outerp) |
| main.go:82:12:82:33 | struct literal [postupdate] | main.go:82:2:82:7 | SSA def(outerp) |
| main.go:83:7:83:12 | outerp | main.go:84:7:84:12 | outerp |
| main.go:84:7:84:12 | outerp | main.go:85:7:85:12 | outerp |
| main.go:85:7:85:12 | outerp | main.go:86:7:86:12 | outerp |
| main.go:90:6:90:10 | definition of outer | main.go:91:2:91:6 | outer |
| main.go:90:6:90:10 | zero value for outer | main.go:90:6:90:10 | definition of outer |
| main.go:90:6:90:10 | SSA def(outer) | main.go:91:2:91:6 | outer |
| main.go:90:6:90:10 | zero value for outer | main.go:90:6:90:10 | SSA def(outer) |
| main.go:91:2:91:6 | outer | main.go:92:7:92:11 | outer |
| main.go:91:2:91:6 | outer [postupdate] | main.go:92:7:92:11 | outer |
| main.go:92:7:92:11 | outer | main.go:93:7:93:11 | outer |
| main.go:93:7:93:11 | outer | main.go:94:7:94:11 | outer |
| main.go:94:7:94:11 | outer | main.go:95:7:95:11 | outer |
| main.go:97:6:97:11 | definition of outerp | main.go:98:2:98:7 | outerp |
| main.go:97:6:97:11 | zero value for outerp | main.go:97:6:97:11 | definition of outerp |
| main.go:97:6:97:11 | SSA def(outerp) | main.go:98:2:98:7 | outerp |
| main.go:97:6:97:11 | zero value for outerp | main.go:97:6:97:11 | SSA def(outerp) |
| main.go:98:2:98:7 | outerp | main.go:99:7:99:12 | outerp |
| main.go:98:2:98:7 | outerp [postupdate] | main.go:99:7:99:12 | outerp |
| main.go:99:7:99:12 | outerp | main.go:100:7:100:12 | outerp |
| main.go:100:7:100:12 | outerp | main.go:101:7:101:12 | outerp |
| main.go:101:7:101:12 | outerp | main.go:102:7:102:12 | outerp |
| main.go:106:6:106:10 | definition of outer | main.go:107:2:107:6 | outer |
| main.go:106:6:106:10 | zero value for outer | main.go:106:6:106:10 | definition of outer |
| main.go:106:6:106:10 | SSA def(outer) | main.go:107:2:107:6 | outer |
| main.go:106:6:106:10 | zero value for outer | main.go:106:6:106:10 | SSA def(outer) |
| main.go:107:2:107:6 | outer | main.go:108:7:108:11 | outer |
| main.go:107:2:107:6 | outer [postupdate] | main.go:108:7:108:11 | outer |
| main.go:108:7:108:11 | outer | main.go:109:7:109:11 | outer |
| main.go:109:7:109:11 | outer | main.go:110:7:110:11 | outer |
| main.go:110:7:110:11 | outer | main.go:111:7:111:11 | outer |
| main.go:113:6:113:11 | definition of outerp | main.go:114:2:114:7 | outerp |
| main.go:113:6:113:11 | zero value for outerp | main.go:113:6:113:11 | definition of outerp |
| main.go:113:6:113:11 | SSA def(outerp) | main.go:114:2:114:7 | outerp |
| main.go:113:6:113:11 | zero value for outerp | main.go:113:6:113:11 | SSA def(outerp) |
| main.go:114:2:114:7 | outerp | main.go:115:7:115:12 | outerp |
| main.go:114:2:114:7 | outerp [postupdate] | main.go:115:7:115:12 | outerp |
| main.go:115:7:115:12 | outerp | main.go:116:7:116:12 | outerp |
| main.go:116:7:116:12 | outerp | main.go:117:7:117:12 | outerp |
| main.go:117:7:117:12 | outerp | main.go:118:7:118:12 | outerp |
| main.go:122:6:122:10 | definition of outer | main.go:123:2:123:6 | outer |
| main.go:122:6:122:10 | zero value for outer | main.go:122:6:122:10 | definition of outer |
| main.go:122:6:122:10 | SSA def(outer) | main.go:123:2:123:6 | outer |
| main.go:122:6:122:10 | zero value for outer | main.go:122:6:122:10 | SSA def(outer) |
| main.go:123:2:123:6 | outer | main.go:124:7:124:11 | outer |
| main.go:123:2:123:6 | outer [postupdate] | main.go:124:7:124:11 | outer |
| main.go:124:7:124:11 | outer | main.go:125:7:125:11 | outer |
| main.go:125:7:125:11 | outer | main.go:126:7:126:11 | outer |
| main.go:126:7:126:11 | outer | main.go:127:7:127:11 | outer |
| main.go:129:6:129:11 | definition of outerp | main.go:130:2:130:7 | outerp |
| main.go:129:6:129:11 | zero value for outerp | main.go:129:6:129:11 | definition of outerp |
| main.go:129:6:129:11 | SSA def(outerp) | main.go:130:2:130:7 | outerp |
| main.go:129:6:129:11 | zero value for outerp | main.go:129:6:129:11 | SSA def(outerp) |
| main.go:130:2:130:7 | outerp | main.go:131:7:131:12 | outerp |
| main.go:130:2:130:7 | outerp [postupdate] | main.go:131:7:131:12 | outerp |
| main.go:131:7:131:12 | outerp | main.go:132:7:132:12 | outerp |
| main.go:132:7:132:12 | outerp | main.go:133:7:133:12 | outerp |
| main.go:133:7:133:12 | outerp | main.go:134:7:134:12 | outerp |
| main.go:138:6:138:10 | definition of outer | main.go:139:2:139:6 | outer |
| main.go:138:6:138:10 | zero value for outer | main.go:138:6:138:10 | definition of outer |
| main.go:138:6:138:10 | SSA def(outer) | main.go:139:2:139:6 | outer |
| main.go:138:6:138:10 | zero value for outer | main.go:138:6:138:10 | SSA def(outer) |
| main.go:139:2:139:6 | outer | main.go:140:7:140:11 | outer |
| main.go:139:2:139:6 | outer [postupdate] | main.go:140:7:140:11 | outer |
| main.go:140:7:140:11 | outer | main.go:141:7:141:11 | outer |
| main.go:141:7:141:11 | outer | main.go:142:7:142:11 | outer |
| main.go:142:7:142:11 | outer | main.go:143:7:143:11 | outer |
| main.go:145:6:145:11 | definition of outerp | main.go:146:2:146:7 | outerp |
| main.go:145:6:145:11 | zero value for outerp | main.go:145:6:145:11 | definition of outerp |
| main.go:145:6:145:11 | SSA def(outerp) | main.go:146:2:146:7 | outerp |
| main.go:145:6:145:11 | zero value for outerp | main.go:145:6:145:11 | SSA def(outerp) |
| main.go:146:2:146:7 | outerp | main.go:147:7:147:12 | outerp |
| main.go:146:2:146:7 | outerp [postupdate] | main.go:147:7:147:12 | outerp |
| main.go:147:7:147:12 | outerp | main.go:148:7:148:12 | outerp |

View File

@@ -1,3 +1,5 @@
reverseRead
| main.go:97:2:97:8 | wrapper | Origin of readStep is missing a PostUpdateNode. |
| main.go:117:2:117:2 | p | Origin of readStep is missing a PostUpdateNode. |
| main.go:105:2:105:8 | wrapper | Origin of readStep is missing a PostUpdateNode. |
| main.go:114:2:114:8 | wrapper | Origin of readStep is missing a PostUpdateNode. |
| main.go:135:2:135:2 | p | Origin of readStep is missing a PostUpdateNode. |

View File

@@ -1,34 +1,42 @@
| main.go:15:12:15:12 | x | main.go:13:6:13:6 | definition of x | main.go:13:6:13:6 | x |
| main.go:15:15:15:15 | y | main.go:14:2:14:2 | definition of y | main.go:14:2:14:2 | y |
| main.go:17:3:17:3 | y | main.go:14:2:14:2 | definition of y | main.go:14:2:14:2 | y |
| main.go:19:12:19:12 | x | main.go:13:6:13:6 | definition of x | main.go:13:6:13:6 | x |
| main.go:19:15:19:15 | y | main.go:19:2:19:10 | y = phi(def@14:2, def@17:3) | main.go:14:2:14:2 | y |
| main.go:21:7:21:7 | y | main.go:19:2:19:10 | y = phi(def@14:2, def@17:3) | main.go:14:2:14:2 | y |
| main.go:23:12:23:12 | x | main.go:23:2:23:10 | x = phi(def@13:6, def@21:3) | main.go:13:6:13:6 | x |
| main.go:23:15:23:15 | y | main.go:19:2:19:10 | y = phi(def@14:2, def@17:3) | main.go:14:2:14:2 | y |
| main.go:27:10:27:10 | x | main.go:26:10:26:10 | definition of x | main.go:26:10:26:10 | x |
| main.go:29:10:29:10 | b | main.go:27:5:27:5 | definition of b | main.go:27:5:27:5 | b |
| main.go:29:13:29:13 | a | main.go:27:2:27:2 | definition of a | main.go:27:2:27:2 | a |
| main.go:31:9:31:9 | a | main.go:31:9:31:9 | a = phi(def@27:2, def@29:3) | main.go:27:2:27:2 | a |
| main.go:31:12:31:12 | b | main.go:31:9:31:9 | b = phi(def@27:5, def@29:6) | main.go:27:5:27:5 | b |
| main.go:35:3:35:3 | x | main.go:34:11:34:11 | definition of x | main.go:34:11:34:11 | x |
| main.go:40:10:40:10 | x | main.go:39:2:39:2 | definition of x | main.go:39:2:39:2 | x |
| main.go:42:8:42:10 | ptr | main.go:40:2:40:4 | definition of ptr | main.go:40:2:40:4 | ptr |
| main.go:44:12:44:12 | x | main.go:39:2:39:2 | definition of x | main.go:39:2:39:2 | x |
| main.go:47:13:47:18 | implicit read of result | main.go:48:2:48:7 | definition of result | main.go:47:13:47:18 | result |
| main.go:52:14:52:19 | implicit read of result | main.go:52:14:52:19 | definition of result | main.go:52:14:52:19 | result |
| main.go:61:12:61:12 | x | main.go:58:6:58:9 | x = phi(def@57:6, def@59:3) | main.go:57:6:57:6 | x |
| main.go:64:16:64:16 | i | main.go:65:6:65:9 | i = phi(def@64:16, def@64:6) | main.go:64:6:64:6 | i |
| main.go:70:12:70:12 | y | main.go:65:6:65:9 | y = phi(def@63:2, def@68:3) | main.go:63:2:63:2 | y |
| main.go:73:16:73:16 | i | main.go:74:3:74:3 | i = phi(def@73:16, def@73:6) | main.go:73:6:73:6 | i |
| main.go:79:12:79:12 | z | main.go:74:3:74:3 | definition of z | main.go:72:2:72:2 | z |
| main.go:82:18:82:18 | implicit read of a | main.go:84:5:84:5 | definition of a | main.go:82:18:82:18 | a |
| main.go:82:25:82:25 | implicit read of b | main.go:82:25:82:25 | definition of b | main.go:82:25:82:25 | b |
| main.go:84:9:84:9 | x | main.go:83:2:83:2 | definition of x | main.go:83:2:83:2 | x |
| main.go:84:15:84:15 | x | main.go:83:2:83:2 | definition of x | main.go:83:2:83:2 | x |
| main.go:97:2:97:8 | wrapper | main.go:95:22:95:28 | definition of wrapper | main.go:95:22:95:28 | wrapper |
| main.go:100:9:100:9 | x | main.go:97:2:99:3 | capture variable x | main.go:96:2:96:2 | x |
| main.go:117:2:117:2 | p | main.go:117:2:117:2 | p = phi(def@112:3, def@114:3) | main.go:110:6:110:6 | p |
| main.go:119:12:119:12 | p | main.go:117:2:117:2 | p = phi(def@112:3, def@114:3) | main.go:110:6:110:6 | p |
| main.go:119:17:119:17 | p | main.go:117:2:117:2 | p = phi(def@112:3, def@114:3) | main.go:110:6:110:6 | p |
| main.go:119:24:119:24 | p | main.go:117:2:117:2 | p = phi(def@112:3, def@114:3) | main.go:110:6:110:6 | p |
| main.go:15:12:15:12 | x | main.go:13:6:13:6 | SSA def(x) | main.go:13:6:13:6 | x |
| main.go:15:15:15:15 | y | main.go:14:2:14:2 | SSA def(y) | main.go:14:2:14:2 | y |
| main.go:17:3:17:3 | y | main.go:14:2:14:2 | SSA def(y) | main.go:14:2:14:2 | y |
| main.go:19:12:19:12 | x | main.go:13:6:13:6 | SSA def(x) | main.go:13:6:13:6 | x |
| main.go:19:15:19:15 | y | main.go:19:2:19:10 | SSA phi(y) | main.go:14:2:14:2 | y |
| main.go:21:7:21:7 | y | main.go:19:2:19:10 | SSA phi(y) | main.go:14:2:14:2 | y |
| main.go:23:12:23:12 | x | main.go:23:2:23:10 | SSA phi(x) | main.go:13:6:13:6 | x |
| main.go:23:15:23:15 | y | main.go:19:2:19:10 | SSA phi(y) | main.go:14:2:14:2 | y |
| main.go:27:10:27:10 | x | main.go:26:10:26:10 | SSA def(x) | main.go:26:10:26:10 | x |
| main.go:29:10:29:10 | b | main.go:27:5:27:5 | SSA def(b) | main.go:27:5:27:5 | b |
| main.go:29:13:29:13 | a | main.go:27:2:27:2 | SSA def(a) | main.go:27:2:27:2 | a |
| main.go:31:9:31:9 | a | main.go:31:9:31:9 | SSA phi(a) | main.go:27:2:27:2 | a |
| main.go:31:12:31:12 | b | main.go:31:9:31:9 | SSA phi(b) | main.go:27:5:27:5 | b |
| main.go:35:3:35:3 | x | main.go:34:11:34:11 | SSA def(x) | main.go:34:11:34:11 | x |
| main.go:40:10:40:10 | x | main.go:39:2:39:2 | SSA def(x) | main.go:39:2:39:2 | x |
| main.go:42:8:42:10 | ptr | main.go:40:2:40:4 | SSA def(ptr) | main.go:40:2:40:4 | ptr |
| main.go:44:12:44:12 | x | main.go:39:2:39:2 | SSA def(x) | main.go:39:2:39:2 | x |
| main.go:47:13:47:18 | implicit read of result | main.go:48:2:48:7 | SSA def(result) | main.go:47:13:47:18 | result |
| main.go:52:14:52:19 | implicit read of result | main.go:52:14:52:19 | SSA def(result) | main.go:52:14:52:19 | result |
| main.go:61:12:61:12 | x | main.go:58:6:58:9 | SSA phi(x) | main.go:57:6:57:6 | x |
| main.go:64:16:64:16 | i | main.go:65:6:65:9 | SSA phi(i) | main.go:64:6:64:6 | i |
| main.go:70:12:70:12 | y | main.go:65:6:65:9 | SSA phi(y) | main.go:63:2:63:2 | y |
| main.go:73:16:73:16 | i | main.go:74:3:74:3 | SSA phi(i) | main.go:73:6:73:6 | i |
| main.go:79:12:79:12 | z | main.go:74:3:74:3 | SSA def(z) | main.go:72:2:72:2 | z |
| main.go:82:18:82:18 | implicit read of a | main.go:84:5:84:5 | SSA def(a) | main.go:82:18:82:18 | a |
| main.go:82:25:82:25 | implicit read of b | main.go:82:25:82:25 | SSA def(b) | main.go:82:25:82:25 | b |
| main.go:84:9:84:9 | x | main.go:83:2:83:2 | SSA def(x) | main.go:83:2:83:2 | x |
| main.go:84:15:84:15 | x | main.go:83:2:83:2 | SSA def(x) | main.go:83:2:83:2 | x |
| main.go:97:2:97:8 | wrapper | main.go:95:22:95:28 | SSA def(wrapper) | main.go:95:22:95:28 | wrapper |
| main.go:100:9:100:9 | x | main.go:97:2:99:3 | SSA def(x) | main.go:96:2:96:2 | x |
| main.go:105:2:105:8 | wrapper | main.go:103:20:103:26 | SSA def(wrapper) | main.go:103:20:103:26 | wrapper |
| main.go:106:8:106:8 | x | main.go:105:16:108:2 | SSA def(x) | main.go:104:2:104:2 | x |
| main.go:107:7:107:7 | y | main.go:106:3:106:3 | SSA def(y) | main.go:106:3:106:3 | y |
| main.go:109:9:109:9 | x | main.go:104:2:104:2 | SSA def(x) | main.go:104:2:104:2 | x |
| main.go:114:2:114:8 | wrapper | main.go:112:29:112:35 | SSA def(wrapper) | main.go:112:29:112:35 | wrapper |
| main.go:115:8:115:8 | x | main.go:114:16:117:2 | SSA def(x) | main.go:113:2:113:2 | x |
| main.go:116:7:116:7 | y | main.go:115:3:115:3 | SSA def(y) | main.go:115:3:115:3 | y |
| main.go:118:9:118:9 | x | main.go:114:2:117:3 | SSA def(x) | main.go:113:2:113:2 | x |
| main.go:135:2:135:2 | p | main.go:135:2:135:2 | SSA phi(p) | main.go:128:6:128:6 | p |
| main.go:137:12:137:12 | p | main.go:135:2:135:2 | SSA phi(p) | main.go:128:6:128:6 | p |
| main.go:137:17:137:17 | p | main.go:135:2:135:2 | SSA phi(p) | main.go:128:6:128:6 | p |
| main.go:137:24:137:24 | p | main.go:135:2:135:2 | SSA phi(p) | main.go:128:6:128:6 | p |

View File

@@ -1,41 +1,51 @@
| main.go:13:6:13:6 | definition of x |
| main.go:14:2:14:2 | definition of y |
| main.go:17:3:17:3 | definition of y |
| main.go:19:2:19:10 | y = phi(def@14:2, def@17:3) |
| main.go:21:3:21:3 | definition of x |
| main.go:23:2:23:10 | x = phi(def@13:6, def@21:3) |
| main.go:26:10:26:10 | definition of x |
| main.go:27:2:27:2 | definition of a |
| main.go:27:5:27:5 | definition of b |
| main.go:29:3:29:3 | definition of a |
| main.go:29:6:29:6 | definition of b |
| main.go:31:9:31:9 | a = phi(def@27:2, def@29:3) |
| main.go:31:9:31:9 | b = phi(def@27:5, def@29:6) |
| main.go:34:11:34:11 | definition of x |
| main.go:39:2:39:2 | definition of x |
| main.go:40:2:40:4 | definition of ptr |
| main.go:48:2:48:7 | definition of result |
| main.go:52:14:52:19 | definition of result |
| main.go:57:6:57:6 | definition of x |
| main.go:58:6:58:9 | x = phi(def@57:6, def@59:3) |
| main.go:59:3:59:3 | definition of x |
| main.go:63:2:63:2 | definition of y |
| main.go:64:6:64:6 | definition of i |
| main.go:64:16:64:18 | definition of i |
| main.go:65:6:65:9 | i = phi(def@64:16, def@64:6) |
| main.go:65:6:65:9 | y = phi(def@63:2, def@68:3) |
| main.go:68:3:68:3 | definition of y |
| main.go:73:6:73:6 | definition of i |
| main.go:73:16:73:18 | definition of i |
| main.go:74:3:74:3 | definition of z |
| main.go:74:3:74:3 | i = phi(def@73:16, def@73:6) |
| main.go:82:25:82:25 | definition of b |
| main.go:83:2:83:2 | definition of x |
| main.go:84:5:84:5 | definition of a |
| main.go:95:22:95:28 | definition of wrapper |
| main.go:96:2:96:2 | definition of x |
| main.go:97:2:99:3 | capture variable x |
| main.go:98:3:98:3 | definition of x |
| main.go:112:3:112:3 | definition of p |
| main.go:114:3:114:3 | definition of p |
| main.go:117:2:117:2 | p = phi(def@112:3, def@114:3) |
| main.go:13:6:13:6 | SSA def(x) |
| main.go:14:2:14:2 | SSA def(y) |
| main.go:17:3:17:3 | SSA def(y) |
| main.go:19:2:19:10 | SSA phi(y) |
| main.go:21:3:21:3 | SSA def(x) |
| main.go:23:2:23:10 | SSA phi(x) |
| main.go:26:10:26:10 | SSA def(x) |
| main.go:27:2:27:2 | SSA def(a) |
| main.go:27:5:27:5 | SSA def(b) |
| main.go:29:3:29:3 | SSA def(a) |
| main.go:29:6:29:6 | SSA def(b) |
| main.go:31:9:31:9 | SSA phi(a) |
| main.go:31:9:31:9 | SSA phi(b) |
| main.go:34:11:34:11 | SSA def(x) |
| main.go:39:2:39:2 | SSA def(x) |
| main.go:40:2:40:4 | SSA def(ptr) |
| main.go:48:2:48:7 | SSA def(result) |
| main.go:52:14:52:19 | SSA def(result) |
| main.go:57:6:57:6 | SSA def(x) |
| main.go:58:6:58:9 | SSA phi(x) |
| main.go:59:3:59:3 | SSA def(x) |
| main.go:63:2:63:2 | SSA def(y) |
| main.go:64:6:64:6 | SSA def(i) |
| main.go:64:16:64:18 | SSA def(i) |
| main.go:65:6:65:9 | SSA phi(i) |
| main.go:65:6:65:9 | SSA phi(y) |
| main.go:68:3:68:3 | SSA def(y) |
| main.go:73:6:73:6 | SSA def(i) |
| main.go:73:16:73:18 | SSA def(i) |
| main.go:74:3:74:3 | SSA def(z) |
| main.go:74:3:74:3 | SSA phi(i) |
| main.go:82:25:82:25 | SSA def(b) |
| main.go:83:2:83:2 | SSA def(x) |
| main.go:84:5:84:5 | SSA def(a) |
| main.go:95:22:95:28 | SSA def(wrapper) |
| main.go:96:2:96:2 | SSA def(x) |
| main.go:97:2:99:3 | SSA def(x) |
| main.go:98:3:98:3 | SSA def(x) |
| main.go:103:20:103:26 | SSA def(wrapper) |
| main.go:104:2:104:2 | SSA def(x) |
| main.go:105:16:108:2 | SSA def(x) |
| main.go:106:3:106:3 | SSA def(y) |
| main.go:112:29:112:35 | SSA def(wrapper) |
| main.go:113:2:113:2 | SSA def(x) |
| main.go:114:2:117:3 | SSA def(x) |
| main.go:114:16:117:2 | SSA def(x) |
| main.go:115:3:115:3 | SSA def(y) |
| main.go:116:3:116:3 | SSA def(x) |
| main.go:130:3:130:3 | SSA def(p) |
| main.go:132:3:132:3 | SSA def(p) |
| main.go:135:2:135:2 | SSA phi(p) |

View File

@@ -1,46 +1,58 @@
| main.go:13:6:13:6 | (def@13:6) | x |
| main.go:14:2:14:2 | (def@14:2) | y |
| main.go:17:3:17:3 | (def@17:3) | y |
| main.go:19:2:19:10 | (phi@19:2) | y |
| main.go:21:3:21:3 | (def@21:3) | x |
| main.go:23:2:23:10 | (phi@23:2) | x |
| main.go:26:10:26:10 | (def@26:10) | x |
| main.go:27:2:27:2 | (def@27:2) | a |
| main.go:27:5:27:5 | (def@27:5) | b |
| main.go:29:3:29:3 | (def@29:3) | a |
| main.go:29:6:29:6 | (def@29:6) | b |
| main.go:31:9:31:9 | (phi@31:9) | a |
| main.go:31:9:31:9 | (phi@31:9) | b |
| main.go:34:11:34:11 | (def@34:11) | x |
| main.go:39:2:39:2 | (def@39:2) | x |
| main.go:40:2:40:4 | (def@40:2) | ptr |
| main.go:48:2:48:7 | (def@48:2) | result |
| main.go:52:14:52:19 | (def@52:14) | result |
| main.go:57:6:57:6 | (def@57:6) | x |
| main.go:58:6:58:9 | (phi@58:6) | x |
| main.go:59:3:59:3 | (def@59:3) | x |
| main.go:63:2:63:2 | (def@63:2) | y |
| main.go:64:6:64:6 | (def@64:6) | i |
| main.go:64:16:64:18 | (def@64:16) | i |
| main.go:65:6:65:9 | (phi@65:6) | i |
| main.go:65:6:65:9 | (phi@65:6) | y |
| main.go:68:3:68:3 | (def@68:3) | y |
| main.go:73:6:73:6 | (def@73:6) | i |
| main.go:73:16:73:18 | (def@73:16) | i |
| main.go:74:3:74:3 | (def@74:3) | z |
| main.go:74:3:74:3 | (phi@74:3) | i |
| main.go:82:25:82:25 | (def@82:25) | b |
| main.go:83:2:83:2 | (def@83:2) | x |
| main.go:84:5:84:5 | (def@84:5) | a |
| main.go:95:22:95:28 | (def@95:22) | wrapper |
| main.go:95:22:95:28 | (def@95:22).s | wrapper.s |
| main.go:96:2:96:2 | (def@96:2) | x |
| main.go:97:2:99:3 | (capture@97:2) | x |
| main.go:98:3:98:3 | (def@98:3) | x |
| main.go:112:3:112:3 | (def@112:3) | p |
| main.go:114:3:114:3 | (def@114:3) | p |
| main.go:117:2:117:2 | (phi@117:2) | p |
| main.go:117:2:117:2 | (phi@117:2).a | p.a |
| main.go:117:2:117:2 | (phi@117:2).b | p.b |
| main.go:117:2:117:2 | (phi@117:2).b.a | p.b.a |
| main.go:117:2:117:2 | (phi@117:2).c | p.c |
| main.go:13:6:13:6 | (SSA def(x)) | x |
| main.go:14:2:14:2 | (SSA def(y)) | y |
| main.go:17:3:17:3 | (SSA def(y)) | y |
| main.go:19:2:19:10 | (SSA phi(y)) | y |
| main.go:21:3:21:3 | (SSA def(x)) | x |
| main.go:23:2:23:10 | (SSA phi(x)) | x |
| main.go:26:10:26:10 | (SSA def(x)) | x |
| main.go:27:2:27:2 | (SSA def(a)) | a |
| main.go:27:5:27:5 | (SSA def(b)) | b |
| main.go:29:3:29:3 | (SSA def(a)) | a |
| main.go:29:6:29:6 | (SSA def(b)) | b |
| main.go:31:9:31:9 | (SSA phi(a)) | a |
| main.go:31:9:31:9 | (SSA phi(b)) | b |
| main.go:34:11:34:11 | (SSA def(x)) | x |
| main.go:39:2:39:2 | (SSA def(x)) | x |
| main.go:40:2:40:4 | (SSA def(ptr)) | ptr |
| main.go:48:2:48:7 | (SSA def(result)) | result |
| main.go:52:14:52:19 | (SSA def(result)) | result |
| main.go:57:6:57:6 | (SSA def(x)) | x |
| main.go:58:6:58:9 | (SSA phi(x)) | x |
| main.go:59:3:59:3 | (SSA def(x)) | x |
| main.go:63:2:63:2 | (SSA def(y)) | y |
| main.go:64:6:64:6 | (SSA def(i)) | i |
| main.go:64:16:64:18 | (SSA def(i)) | i |
| main.go:65:6:65:9 | (SSA phi(i)) | i |
| main.go:65:6:65:9 | (SSA phi(y)) | y |
| main.go:68:3:68:3 | (SSA def(y)) | y |
| main.go:73:6:73:6 | (SSA def(i)) | i |
| main.go:73:16:73:18 | (SSA def(i)) | i |
| main.go:74:3:74:3 | (SSA def(z)) | z |
| main.go:74:3:74:3 | (SSA phi(i)) | i |
| main.go:82:25:82:25 | (SSA def(b)) | b |
| main.go:83:2:83:2 | (SSA def(x)) | x |
| main.go:84:5:84:5 | (SSA def(a)) | a |
| main.go:95:22:95:28 | (SSA def(wrapper)) | wrapper |
| main.go:95:22:95:28 | (SSA def(wrapper)).s | wrapper.s |
| main.go:96:2:96:2 | (SSA def(x)) | x |
| main.go:97:2:99:3 | (SSA def(x)) | x |
| main.go:98:3:98:3 | (SSA def(x)) | x |
| main.go:103:20:103:26 | (SSA def(wrapper)) | wrapper |
| main.go:103:20:103:26 | (SSA def(wrapper)).s | wrapper.s |
| main.go:104:2:104:2 | (SSA def(x)) | x |
| main.go:105:16:108:2 | (SSA def(x)) | x |
| main.go:106:3:106:3 | (SSA def(y)) | y |
| main.go:112:29:112:35 | (SSA def(wrapper)) | wrapper |
| main.go:112:29:112:35 | (SSA def(wrapper)).s | wrapper.s |
| main.go:113:2:113:2 | (SSA def(x)) | x |
| main.go:114:2:117:3 | (SSA def(x)) | x |
| main.go:114:16:117:2 | (SSA def(x)) | x |
| main.go:115:3:115:3 | (SSA def(y)) | y |
| main.go:116:3:116:3 | (SSA def(x)) | x |
| main.go:130:3:130:3 | (SSA def(p)) | p |
| main.go:132:3:132:3 | (SSA def(p)) | p |
| main.go:135:2:135:2 | (SSA phi(p)) | p |
| main.go:135:2:135:2 | (SSA phi(p)).a | p.a |
| main.go:135:2:135:2 | (SSA phi(p)).b | p.b |
| main.go:135:2:135:2 | (SSA phi(p)).b.a | p.b.a |
| main.go:135:2:135:2 | (SSA phi(p)).c | p.c |

View File

@@ -32,16 +32,23 @@
| main.go:95:22:95:28 | initialization of wrapper | main.go:95:22:95:28 | wrapper | main.go:95:22:95:28 | argument corresponding to wrapper |
| main.go:96:2:96:2 | assignment to x | main.go:96:2:96:2 | x | main.go:96:7:96:7 | 0 |
| main.go:98:3:98:3 | assignment to x | main.go:96:2:96:2 | x | main.go:98:7:98:7 | 1 |
| main.go:110:6:110:6 | assignment to p | main.go:110:6:110:6 | p | main.go:110:6:110:6 | zero value for p |
| main.go:112:3:112:3 | assignment to p | main.go:110:6:110:6 | p | main.go:112:7:112:24 | struct literal |
| main.go:112:9:112:9 | init of 2 | main.go:104:2:104:2 | a | main.go:112:9:112:9 | 2 |
| main.go:112:12:112:18 | init of struct literal | main.go:105:2:105:2 | b | main.go:112:12:112:18 | struct literal |
| main.go:112:14:112:14 | init of 1 | main.go:89:2:89:2 | a | main.go:112:14:112:14 | 1 |
| main.go:112:17:112:17 | init of 5 | main.go:90:2:90:2 | b | main.go:112:17:112:17 | 5 |
| main.go:112:21:112:23 | init of 'n' | main.go:106:2:106:2 | c | main.go:112:21:112:23 | 'n' |
| main.go:114:3:114:3 | assignment to p | main.go:110:6:110:6 | p | main.go:114:7:114:24 | struct literal |
| main.go:114:9:114:9 | init of 3 | main.go:104:2:104:2 | a | main.go:114:9:114:9 | 3 |
| main.go:114:12:114:18 | init of struct literal | main.go:105:2:105:2 | b | main.go:114:12:114:18 | struct literal |
| main.go:114:14:114:14 | init of 4 | main.go:89:2:89:2 | a | main.go:114:14:114:14 | 4 |
| main.go:114:17:114:17 | init of 5 | main.go:90:2:90:2 | b | main.go:114:17:114:17 | 5 |
| main.go:114:21:114:23 | init of '2' | main.go:106:2:106:2 | c | main.go:114:21:114:23 | '2' |
| main.go:103:20:103:26 | initialization of wrapper | main.go:103:20:103:26 | wrapper | main.go:103:20:103:26 | argument corresponding to wrapper |
| main.go:104:2:104:2 | assignment to x | main.go:104:2:104:2 | x | main.go:104:7:104:7 | 0 |
| main.go:106:3:106:3 | assignment to y | main.go:106:3:106:3 | y | main.go:106:8:106:8 | x |
| main.go:112:29:112:35 | initialization of wrapper | main.go:112:29:112:35 | wrapper | main.go:112:29:112:35 | argument corresponding to wrapper |
| main.go:113:2:113:2 | assignment to x | main.go:113:2:113:2 | x | main.go:113:7:113:7 | 0 |
| main.go:115:3:115:3 | assignment to y | main.go:115:3:115:3 | y | main.go:115:8:115:12 | ...+... |
| main.go:116:3:116:3 | assignment to x | main.go:113:2:113:2 | x | main.go:116:7:116:7 | y |
| main.go:128:6:128:6 | assignment to p | main.go:128:6:128:6 | p | main.go:128:6:128:6 | zero value for p |
| main.go:130:3:130:3 | assignment to p | main.go:128:6:128:6 | p | main.go:130:7:130:24 | struct literal |
| main.go:130:9:130:9 | init of 2 | main.go:122:2:122:2 | a | main.go:130:9:130:9 | 2 |
| main.go:130:12:130:18 | init of struct literal | main.go:123:2:123:2 | b | main.go:130:12:130:18 | struct literal |
| main.go:130:14:130:14 | init of 1 | main.go:89:2:89:2 | a | main.go:130:14:130:14 | 1 |
| main.go:130:17:130:17 | init of 5 | main.go:90:2:90:2 | b | main.go:130:17:130:17 | 5 |
| main.go:130:21:130:23 | init of 'n' | main.go:124:2:124:2 | c | main.go:130:21:130:23 | 'n' |
| main.go:132:3:132:3 | assignment to p | main.go:128:6:128:6 | p | main.go:132:7:132:24 | struct literal |
| main.go:132:9:132:9 | init of 3 | main.go:122:2:122:2 | a | main.go:132:9:132:9 | 3 |
| main.go:132:12:132:18 | init of struct literal | main.go:123:2:123:2 | b | main.go:132:12:132:18 | struct literal |
| main.go:132:14:132:14 | init of 4 | main.go:89:2:89:2 | a | main.go:132:14:132:14 | 4 |
| main.go:132:17:132:17 | init of 5 | main.go:90:2:90:2 | b | main.go:132:17:132:17 | 5 |
| main.go:132:21:132:23 | init of '2' | main.go:124:2:124:2 | c | main.go:132:21:132:23 | '2' |

View File

@@ -28,13 +28,29 @@
| main.go:84:15:84:15 | x | main.go:83:2:83:2 | x |
| main.go:97:2:97:8 | wrapper | main.go:95:22:95:28 | wrapper |
| main.go:97:2:97:10 | selection of s | main.go:95:38:95:38 | s |
| main.go:97:2:97:10 | selection of s | main.go:103:36:103:36 | s |
| main.go:97:2:97:10 | selection of s | main.go:112:45:112:45 | s |
| main.go:100:9:100:9 | x | main.go:96:2:96:2 | x |
| main.go:117:2:117:2 | p | main.go:110:6:110:6 | p |
| main.go:117:2:117:4 | selection of b | main.go:105:2:105:2 | b |
| main.go:119:12:119:12 | p | main.go:110:6:110:6 | p |
| main.go:119:12:119:14 | selection of a | main.go:104:2:104:2 | a |
| main.go:119:17:119:17 | p | main.go:110:6:110:6 | p |
| main.go:119:17:119:19 | selection of b | main.go:105:2:105:2 | b |
| main.go:119:17:119:21 | selection of a | main.go:89:2:89:2 | a |
| main.go:119:24:119:24 | p | main.go:110:6:110:6 | p |
| main.go:119:24:119:26 | selection of c | main.go:106:2:106:2 | c |
| main.go:105:2:105:8 | wrapper | main.go:103:20:103:26 | wrapper |
| main.go:105:2:105:10 | selection of s | main.go:95:38:95:38 | s |
| main.go:105:2:105:10 | selection of s | main.go:103:36:103:36 | s |
| main.go:105:2:105:10 | selection of s | main.go:112:45:112:45 | s |
| main.go:106:8:106:8 | x | main.go:104:2:104:2 | x |
| main.go:107:7:107:7 | y | main.go:106:3:106:3 | y |
| main.go:109:9:109:9 | x | main.go:104:2:104:2 | x |
| main.go:114:2:114:8 | wrapper | main.go:112:29:112:35 | wrapper |
| main.go:114:2:114:10 | selection of s | main.go:95:38:95:38 | s |
| main.go:114:2:114:10 | selection of s | main.go:103:36:103:36 | s |
| main.go:114:2:114:10 | selection of s | main.go:112:45:112:45 | s |
| main.go:115:8:115:8 | x | main.go:113:2:113:2 | x |
| main.go:116:7:116:7 | y | main.go:115:3:115:3 | y |
| main.go:118:9:118:9 | x | main.go:113:2:113:2 | x |
| main.go:135:2:135:2 | p | main.go:128:6:128:6 | p |
| main.go:135:2:135:4 | selection of b | main.go:123:2:123:2 | b |
| main.go:137:12:137:12 | p | main.go:128:6:128:6 | p |
| main.go:137:12:137:14 | selection of a | main.go:122:2:122:2 | a |
| main.go:137:17:137:17 | p | main.go:128:6:128:6 | p |
| main.go:137:17:137:19 | selection of b | main.go:123:2:123:2 | b |
| main.go:137:17:137:21 | selection of a | main.go:89:2:89:2 | a |
| main.go:137:24:137:24 | p | main.go:128:6:128:6 | p |
| main.go:137:24:137:26 | selection of c | main.go:124:2:124:2 | c |

View File

@@ -100,6 +100,24 @@ func updateInClosure(wrapper struct{ s }) int {
return x
}
func readInClosure(wrapper struct{ s }) int {
x := 0
wrapper.s.foo(func() {
y := x
_ = y
})
return x
}
func readAndUpdateInClosure(wrapper struct{ s }) int {
x := 0
wrapper.s.foo(func() {
y := x + 1
x = y
})
return x
}
type t struct {
a int
b s

View File

@@ -1,73 +1,73 @@
#select
| test.go:154:14:154:21 | password | test.go:153:17:153:24 | definition of password | test.go:154:14:154:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:155:17:155:24 | password | test.go:153:17:153:24 | definition of password | test.go:155:17:155:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:156:14:156:21 | password | test.go:153:17:153:24 | definition of password | test.go:156:14:156:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:157:18:157:25 | password | test.go:153:17:153:24 | definition of password | test.go:157:18:157:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:158:14:158:21 | password | test.go:153:17:153:24 | definition of password | test.go:158:14:158:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:159:13:159:20 | password | test.go:153:17:153:24 | definition of password | test.go:159:13:159:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:160:22:160:29 | password | test.go:153:17:153:24 | definition of password | test.go:160:22:160:29 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:161:15:161:22 | password | test.go:153:17:153:24 | definition of password | test.go:161:15:161:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:162:14:162:21 | password | test.go:153:17:153:24 | definition of password | test.go:162:14:162:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:163:13:163:20 | password | test.go:153:17:153:24 | definition of password | test.go:163:13:163:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:164:16:164:23 | password | test.go:153:17:153:24 | definition of password | test.go:164:16:164:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:165:13:165:20 | password | test.go:153:17:153:24 | definition of password | test.go:165:13:165:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:166:16:166:23 | password | test.go:153:17:153:24 | definition of password | test.go:166:16:166:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:167:13:167:20 | password | test.go:153:17:153:24 | definition of password | test.go:167:13:167:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:168:17:168:24 | password | test.go:153:17:153:24 | definition of password | test.go:168:17:168:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:169:13:169:20 | password | test.go:153:17:153:24 | definition of password | test.go:169:13:169:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:170:12:170:19 | password | test.go:153:17:153:24 | definition of password | test.go:170:12:170:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:171:21:171:28 | password | test.go:153:17:153:24 | definition of password | test.go:171:21:171:28 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:172:14:172:21 | password | test.go:153:17:153:24 | definition of password | test.go:172:14:172:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:173:13:173:20 | password | test.go:153:17:153:24 | definition of password | test.go:173:13:173:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:174:12:174:19 | password | test.go:153:17:153:24 | definition of password | test.go:174:12:174:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:175:15:175:22 | password | test.go:153:17:153:24 | definition of password | test.go:175:15:175:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:176:15:176:22 | password | test.go:153:17:153:24 | definition of password | test.go:176:15:176:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:177:18:177:25 | password | test.go:153:17:153:24 | definition of password | test.go:177:18:177:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:178:15:178:22 | password | test.go:153:17:153:24 | definition of password | test.go:178:15:178:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:179:19:179:26 | password | test.go:153:17:153:24 | definition of password | test.go:179:19:179:26 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:180:15:180:22 | password | test.go:153:17:153:24 | definition of password | test.go:180:15:180:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:181:14:181:21 | password | test.go:153:17:153:24 | definition of password | test.go:181:14:181:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:182:23:182:30 | password | test.go:153:17:153:24 | definition of password | test.go:182:23:182:30 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:183:16:183:23 | password | test.go:153:17:153:24 | definition of password | test.go:183:16:183:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:184:15:184:22 | password | test.go:153:17:153:24 | definition of password | test.go:184:15:184:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:185:14:185:21 | password | test.go:153:17:153:24 | definition of password | test.go:185:14:185:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:186:17:186:24 | password | test.go:153:17:153:24 | definition of password | test.go:186:17:186:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:187:16:187:23 | password | test.go:153:17:153:24 | definition of password | test.go:187:16:187:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | definition of password | Sensitive data returned by an access to password |
| test.go:154:14:154:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:154:14:154:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:155:17:155:24 | password | test.go:153:17:153:24 | SSA def(password) | test.go:155:17:155:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:156:14:156:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:156:14:156:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:157:18:157:25 | password | test.go:153:17:153:24 | SSA def(password) | test.go:157:18:157:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:158:14:158:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:158:14:158:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:159:13:159:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:159:13:159:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:160:22:160:29 | password | test.go:153:17:153:24 | SSA def(password) | test.go:160:22:160:29 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:161:15:161:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:161:15:161:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:162:14:162:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:162:14:162:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:163:13:163:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:163:13:163:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:164:16:164:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:164:16:164:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:165:13:165:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:165:13:165:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:166:16:166:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:166:16:166:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:167:13:167:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:167:13:167:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:168:17:168:24 | password | test.go:153:17:153:24 | SSA def(password) | test.go:168:17:168:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:169:13:169:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:169:13:169:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:170:12:170:19 | password | test.go:153:17:153:24 | SSA def(password) | test.go:170:12:170:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:171:21:171:28 | password | test.go:153:17:153:24 | SSA def(password) | test.go:171:21:171:28 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:172:14:172:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:172:14:172:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:173:13:173:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:173:13:173:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:174:12:174:19 | password | test.go:153:17:153:24 | SSA def(password) | test.go:174:12:174:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:175:15:175:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:175:15:175:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:176:15:176:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:176:15:176:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:177:18:177:25 | password | test.go:153:17:153:24 | SSA def(password) | test.go:177:18:177:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:178:15:178:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:178:15:178:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:179:19:179:26 | password | test.go:153:17:153:24 | SSA def(password) | test.go:179:19:179:26 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:180:15:180:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:180:15:180:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:181:14:181:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:181:14:181:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:182:23:182:30 | password | test.go:153:17:153:24 | SSA def(password) | test.go:182:23:182:30 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:183:16:183:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:183:16:183:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:184:15:184:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:184:15:184:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:185:14:185:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:185:14:185:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:186:17:186:24 | password | test.go:153:17:153:24 | SSA def(password) | test.go:186:17:186:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
| test.go:187:16:187:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:187:16:187:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password |
edges
| test.go:153:17:153:24 | definition of password | test.go:154:14:154:21 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:155:17:155:24 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:156:14:156:21 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:157:18:157:25 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:158:14:158:21 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:159:13:159:20 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:160:22:160:29 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:161:15:161:22 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:162:14:162:21 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:163:13:163:20 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:164:16:164:23 | password | provenance | |
| test.go:153:17:153:24 | definition of password | test.go:165:13:165:20 | password | provenance | Sink:MaD:1 |
| test.go:153:17:153:24 | definition of password | test.go:166:16:166:23 | password | provenance | Sink:MaD:2 |
| test.go:153:17:153:24 | definition of password | test.go:167:13:167:20 | password | provenance | Sink:MaD:3 |
| test.go:153:17:153:24 | definition of password | test.go:168:17:168:24 | password | provenance | Sink:MaD:4 |
| test.go:153:17:153:24 | definition of password | test.go:169:13:169:20 | password | provenance | Sink:MaD:5 |
| test.go:153:17:153:24 | definition of password | test.go:170:12:170:19 | password | provenance | Sink:MaD:6 |
| test.go:153:17:153:24 | definition of password | test.go:171:21:171:28 | password | provenance | Sink:MaD:7 |
| test.go:153:17:153:24 | definition of password | test.go:172:14:172:21 | password | provenance | Sink:MaD:8 |
| test.go:153:17:153:24 | definition of password | test.go:173:13:173:20 | password | provenance | Sink:MaD:9 |
| test.go:153:17:153:24 | definition of password | test.go:174:12:174:19 | password | provenance | Sink:MaD:10 |
| test.go:153:17:153:24 | definition of password | test.go:175:15:175:22 | password | provenance | Sink:MaD:11 |
| test.go:153:17:153:24 | definition of password | test.go:176:15:176:22 | password | provenance | Sink:MaD:12 |
| test.go:153:17:153:24 | definition of password | test.go:177:18:177:25 | password | provenance | Sink:MaD:13 |
| test.go:153:17:153:24 | definition of password | test.go:178:15:178:22 | password | provenance | Sink:MaD:14 |
| test.go:153:17:153:24 | definition of password | test.go:179:19:179:26 | password | provenance | Sink:MaD:15 |
| test.go:153:17:153:24 | definition of password | test.go:180:15:180:22 | password | provenance | Sink:MaD:16 |
| test.go:153:17:153:24 | definition of password | test.go:181:14:181:21 | password | provenance | Sink:MaD:17 |
| test.go:153:17:153:24 | definition of password | test.go:182:23:182:30 | password | provenance | Sink:MaD:18 |
| test.go:153:17:153:24 | definition of password | test.go:183:16:183:23 | password | provenance | Sink:MaD:19 |
| test.go:153:17:153:24 | definition of password | test.go:184:15:184:22 | password | provenance | Sink:MaD:20 |
| test.go:153:17:153:24 | definition of password | test.go:185:14:185:21 | password | provenance | Sink:MaD:21 |
| test.go:153:17:153:24 | definition of password | test.go:186:17:186:24 | password | provenance | Sink:MaD:22 |
| test.go:153:17:153:24 | definition of password | test.go:187:16:187:23 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:154:14:154:21 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:155:17:155:24 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:156:14:156:21 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:157:18:157:25 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:158:14:158:21 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:159:13:159:20 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:160:22:160:29 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:161:15:161:22 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:162:14:162:21 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:163:13:163:20 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:164:16:164:23 | password | provenance | |
| test.go:153:17:153:24 | SSA def(password) | test.go:165:13:165:20 | password | provenance | Sink:MaD:1 |
| test.go:153:17:153:24 | SSA def(password) | test.go:166:16:166:23 | password | provenance | Sink:MaD:2 |
| test.go:153:17:153:24 | SSA def(password) | test.go:167:13:167:20 | password | provenance | Sink:MaD:3 |
| test.go:153:17:153:24 | SSA def(password) | test.go:168:17:168:24 | password | provenance | Sink:MaD:4 |
| test.go:153:17:153:24 | SSA def(password) | test.go:169:13:169:20 | password | provenance | Sink:MaD:5 |
| test.go:153:17:153:24 | SSA def(password) | test.go:170:12:170:19 | password | provenance | Sink:MaD:6 |
| test.go:153:17:153:24 | SSA def(password) | test.go:171:21:171:28 | password | provenance | Sink:MaD:7 |
| test.go:153:17:153:24 | SSA def(password) | test.go:172:14:172:21 | password | provenance | Sink:MaD:8 |
| test.go:153:17:153:24 | SSA def(password) | test.go:173:13:173:20 | password | provenance | Sink:MaD:9 |
| test.go:153:17:153:24 | SSA def(password) | test.go:174:12:174:19 | password | provenance | Sink:MaD:10 |
| test.go:153:17:153:24 | SSA def(password) | test.go:175:15:175:22 | password | provenance | Sink:MaD:11 |
| test.go:153:17:153:24 | SSA def(password) | test.go:176:15:176:22 | password | provenance | Sink:MaD:12 |
| test.go:153:17:153:24 | SSA def(password) | test.go:177:18:177:25 | password | provenance | Sink:MaD:13 |
| test.go:153:17:153:24 | SSA def(password) | test.go:178:15:178:22 | password | provenance | Sink:MaD:14 |
| test.go:153:17:153:24 | SSA def(password) | test.go:179:19:179:26 | password | provenance | Sink:MaD:15 |
| test.go:153:17:153:24 | SSA def(password) | test.go:180:15:180:22 | password | provenance | Sink:MaD:16 |
| test.go:153:17:153:24 | SSA def(password) | test.go:181:14:181:21 | password | provenance | Sink:MaD:17 |
| test.go:153:17:153:24 | SSA def(password) | test.go:182:23:182:30 | password | provenance | Sink:MaD:18 |
| test.go:153:17:153:24 | SSA def(password) | test.go:183:16:183:23 | password | provenance | Sink:MaD:19 |
| test.go:153:17:153:24 | SSA def(password) | test.go:184:15:184:22 | password | provenance | Sink:MaD:20 |
| test.go:153:17:153:24 | SSA def(password) | test.go:185:14:185:21 | password | provenance | Sink:MaD:21 |
| test.go:153:17:153:24 | SSA def(password) | test.go:186:17:186:24 | password | provenance | Sink:MaD:22 |
| test.go:153:17:153:24 | SSA def(password) | test.go:187:16:187:23 | password | provenance | |
models
| 1 | Sink: group:beego-logs; ; false; Alert; ; ; Argument[0..1]; log-injection; manual |
| 2 | Sink: group:beego-logs; ; false; Critical; ; ; Argument[0..1]; log-injection; manual |
@@ -92,7 +92,7 @@ models
| 21 | Sink: group:beego-logs; BeeLogger; true; Warn; ; ; Argument[0..1]; log-injection; manual |
| 22 | Sink: group:beego-logs; BeeLogger; true; Warning; ; ; Argument[0..1]; log-injection; manual |
nodes
| test.go:153:17:153:24 | definition of password | semmle.label | definition of password |
| test.go:153:17:153:24 | SSA def(password) | semmle.label | SSA def(password) |
| test.go:154:14:154:21 | password | semmle.label | password |
| test.go:155:17:155:24 | password | semmle.label | password |
| test.go:156:14:156:21 | password | semmle.label | password |

View File

@@ -12,12 +12,12 @@ type MyService interface {
}
func makeEndpointLit(svc MyService) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) { // $ source="definition of request"
return func(_ context.Context, request interface{}) (interface{}, error) { // $ source="SSA def(request)"
return request, nil
}
}
func endpointfn(_ context.Context, request interface{}) (interface{}, error) { // $ source="definition of request"
func endpointfn(_ context.Context, request interface{}) (interface{}, error) { // $ source="SSA def(request)"
return request, nil
}

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