Compare commits

..

151 Commits

Author SHA1 Message Date
Robert Marsh
06be3aec3e C++: fix duplicated UnreachedInstruction in raw IR 2023-05-01 17:39:23 -04:00
Robert Marsh
cb93684287 C++: more UnreachedInstruction fixes 2023-05-01 17:35:37 -04:00
Robert Marsh
fd1ade8e50 C#: Add hasUnreachedInstruction to raw IR 2023-05-01 17:35:36 -04:00
Robert Marsh
536f9f9cca C++/C#: format and sync identical files 2023-05-01 17:35:36 -04:00
Robert Marsh
f4d3cdeca9 C++: use Options::exits() for noreturn functions 2023-05-01 17:35:36 -04:00
Robert Marsh
d0c603f2eb C++: handle calls to noreturn functions 2023-05-01 17:35:28 -04:00
Tom Hvitved
fc66aacf92 Merge pull request #12922 from hvitved/ruby/controller-template-file-join
Ruby: Fix bad join in `controllerTemplateFile`
2023-04-26 21:26:54 +02:00
Henry Mercer
1ae116c4cc Merge pull request #12895 from github/henrymercer/diagnostics-verify-one-based
JS: Update `DiagnosticLocation` call to gracefully handle invalid locations
2023-04-26 19:22:57 +01:00
Henry Mercer
d7474f91dc Merge branch 'main' into henrymercer/diagnostics-verify-one-based 2023-04-26 17:26:36 +01:00
Arthur Baars
128d102bbc Merge pull request #12871 from aibaars/py-yaml
Python: add YAML support
2023-04-26 18:13:26 +02:00
Mathias Vorreiter Pedersen
20f555c715 Merge pull request #12938 from MathiasVP/fix-todo-is-abnormal-exit-type
Swift: Implement `isAbnormalExitType`
2023-04-26 16:16:19 +01:00
Sam Browning
35788162ec Merge pull request #12915 from github/sabrowning1/query-suite-name-fix
Update `code-scanning` query suite name to `default`
2023-04-26 10:38:21 -04:00
Mathias Vorreiter Pedersen
d114388470 Swift: Implement 'isAbnormalExitType' and accept test changes. 2023-04-26 15:36:52 +01:00
Tony Torralba
12d181143f Merge pull request #10533 from pwntester/main
Java: Add support for java.util.StringJoiner
2023-04-26 16:18:35 +02:00
Michael Nebel
3c1456bd02 Merge pull request #12913 from michaelnebel/csharp/inappropriateencoding
C#: Re-factor the InappropriateEncoding query to use the new API.
2023-04-26 14:45:13 +02:00
Anders Schack-Mulligen
8fcfc6f4f1 Merge pull request #12934 from aschackmull/swift/no-pp-dataflowtype
Swift: Remove empty string DataFlowType in PathNode.
2023-04-26 14:42:27 +02:00
Tony Torralba
5d80f0818c Fix TestModels test expectation 2023-04-26 14:32:28 +02:00
Asger F
b696936d10 Merge pull request #12921 from asgerf/js/typescript-compiler-crash
JS: Fix extractor crash related to recursive generic type alias
2023-04-26 14:21:57 +02:00
Anders Schack-Mulligen
74242638e2 Swift: One more expected output fix. 2023-04-26 14:10:13 +02:00
Anders Schack-Mulligen
8ca5484dcf Merge pull request #12933 from aschackmull/ruby/no-pp-dataflowtype
Ruby: Remove empty string DataFlowType in PathNode.
2023-04-26 14:03:56 +02:00
Arthur Baars
5b6d3afd89 Python: Yaml printAst and tests 2023-04-26 13:41:57 +02:00
Anders Schack-Mulligen
9fe5462b1b Swift: Update more expected output. 2023-04-26 13:41:50 +02:00
Anders Schack-Mulligen
09d4fe21e8 Ruby: Update more expected output. 2023-04-26 13:37:07 +02:00
Anders Schack-Mulligen
6b049cb37a Swift: Update expected output. 2023-04-26 13:15:39 +02:00
Anders Schack-Mulligen
3d01763092 Swift: Remove empty string DataFlowType in PathNode. 2023-04-26 13:10:01 +02:00
Anders Schack-Mulligen
90f84bb516 Ruby: Update expected output. 2023-04-26 13:08:16 +02:00
Anders Schack-Mulligen
81ce6c7779 Ruby: Remove empty string DataFlowType in PathNode. 2023-04-26 12:54:41 +02:00
Asger F
c9c281cb9a JS: Change note 2023-04-26 12:50:59 +02:00
Arthur Baars
c1c2bcf419 Python: rename YAML.qll to Yaml.qll 2023-04-26 12:44:53 +02:00
Tony Torralba
0094c25791 Fix StringJoiner.add models 2023-04-26 12:40:04 +02:00
Asger F
a446c5452d JS: Update test output 2023-04-26 11:44:56 +02:00
Asger F
799d92b218 TS: Fix self-reference check for alias types 2023-04-26 11:44:56 +02:00
Michael Nebel
f32b8ad5b1 C#: Update comment for the RequiresEncodingConfig param module. 2023-04-26 10:32:23 +02:00
Michael Nebel
96fba2dac3 Apply suggestions from code review
Co-authored-by: Michael B. Gale <mbg@github.com>
2023-04-26 10:23:52 +02:00
Tony Torralba
4c102ab99c Refactor to models-as-data 2023-04-26 10:13:15 +02:00
Michael Nebel
bc08d67f19 Merge pull request #12925 from github/workflow/coverage/update
Update CSV framework coverage reports
2023-04-26 10:11:15 +02:00
Tony Torralba
2c4246f29a Fix test comments 2023-04-26 10:08:18 +02:00
Tony Torralba
389e8c4fe8 Add review suggestions 2023-04-26 10:08:16 +02:00
Tony Torralba
0650c016f6 Add models for StringJoiner constructor 2023-04-26 10:07:59 +02:00
Tony Torralba
d54c444606 Add change note 2023-04-26 10:07:49 +02:00
Tony Torralba
311498841e Add fluent models
Add tests
2023-04-26 10:07:27 +02:00
Paolo Tranquilli
9d80a43d6a Merge pull request #12500 from github/redsun82/swift-dispatcher-rework
Swift: rework fetching and dispatching
2023-04-26 09:58:19 +02:00
Erik Krogh Kristensen
6110b7aca5 Merge pull request #12926 from github/dependabot/cargo/ql/tracing-0.1.38
Bump tracing from 0.1.37 to 0.1.38 in /ql
2023-04-26 09:49:55 +02:00
dependabot[bot]
738e3857e7 Bump tracing from 0.1.37 to 0.1.38 in /ql
Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.37 to 0.1.38.
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.37...tracing-0.1.38)

---
updated-dependencies:
- dependency-name: tracing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-26 04:04:15 +00:00
github-actions[bot]
cb82bd62e7 Add changed framework coverage reports 2023-04-26 00:15:23 +00:00
Edward Minnix III
e50f56cc56 Merge pull request #12917 from egregius313/egregius313/java/dataflow/refactor-inline-flow-test
Java: Refactor `InlineFlowTest` to remove usage of `DataFlow::Configuration` API
2023-04-25 16:18:56 -04:00
Tom Hvitved
e5f2b90aec Ruby: Fix bad join in controllerTemplateFile
Before
```
Evaluated relational algebra for predicate ActionController#32b59475::controllerTemplateFile#2#ff@6f4b2395 with tuple counts:
        31304524   ~0%    {2} r1 = JOIN locations_default_10#join_rhs WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff ON FIRST 1 OUTPUT Lhs.1, Rhs.1
           34453   ~3%    {2} r2 = JOIN r1 WITH DataFlowPublic#e1781e31::ModuleNode::getLocation#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1

            1236   ~0%    {2} r3 = JOIN r2 WITH ActionController#32b59475::ActionControllerClass#f ON FIRST 1 OUTPUT Lhs.0, InverseAppend(("" ++ "app/controllers/"),"_controller.rb",Lhs.1)

            1236   ~1%    {2} r4 = SCAN r3 OUTPUT In.0, ("" ++ "app/views/layouts/" ++ In.1 ++ "%")

            1320   ~1%    {3} r5 = JOIN r2 WITH ActionController#32b59475::ActionControllerClass#f ON FIRST 1 OUTPUT Lhs.1, Lhs.0, "^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$"
              14   ~7%    {5} r6 = JOIN r5 WITH PRIMITIVE regexpCapture#bbff ON Lhs.0,Lhs.2
              14   ~7%    {5} r7 = SELECT r6 ON In.3 = 1
              14   ~0%    {3} r8 = SCAN r7 OUTPUT In.1, In.4, InverseAppend((In.4 ++ "app/controllers/"),"_controller.rb",In.0)

              14   ~0%    {2} r9 = SCAN r8 OUTPUT In.0, (In.1 ++ "app/views/layouts/" ++ In.2 ++ "%")

            1250   ~1%    {2} r10 = r4 UNION r9
         8813750   ~2%    {3} r11 = JOIN r10 WITH Erb#b2b9e6ed::ErbFile#ff CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0, Lhs.1
         8813750   ~6%    {4} r12 = JOIN r11 WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.0, Rhs.1
              41   ~6%    {4} r13 = SELECT r12 ON In.3 matches In.1
              41   ~0%    {2} r14 = SCAN r13 OUTPUT In.0, In.2

            1236   ~0%    {2} r15 = SCAN r3 OUTPUT ("" ++ "app/views/" ++ In.1), In.0

              14   ~0%    {2} r16 = SCAN r8 OUTPUT (In.1 ++ "app/views/" ++ In.2), In.0

            1250   ~0%    {2} r17 = r15 UNION r16
             581   ~0%    {2} r18 = JOIN r17 WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1
            3243   ~2%    {2} r19 = JOIN r18 WITH containerparent ON FIRST 1 OUTPUT Rhs.1, Lhs.1
            2767   ~0%    {2} r20 = JOIN r19 WITH Erb#b2b9e6ed::ErbFile#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.0

            2808   ~0%    {2} r21 = r14 UNION r20
                          return r21
```

After
```
Evaluated relational algebra for predicate ActionController#32b59475::controllerTemplateFile#2#ff@4b56c4f9 with tuple counts:
          1236   ~0%    {2} r1 = SCAN ActionController#32b59475::getActionControllerClassRelativePath#1#ff OUTPUT In.0, InverseAppend(("" ++ "app/controllers/"),"_controller.rb",In.1)

          1236   ~0%    {2} r2 = SCAN r1 OUTPUT ("" ++ "app/views/" ++ In.1), In.0

          1320   ~0%    {3} r3 = SCAN ActionController#32b59475::getActionControllerClassRelativePath#1#ff OUTPUT In.0, In.1, "^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$"
            14   ~0%    {5} r4 = JOIN r3 WITH PRIMITIVE regexpCapture#bbff ON Lhs.1,Lhs.2
            14   ~0%    {5} r5 = SELECT r4 ON In.3 = 1
            14   ~0%    {3} r6 = SCAN r5 OUTPUT In.0, In.4, InverseAppend((In.4 ++ "app/controllers/"),"_controller.rb",In.1)

            14   ~0%    {2} r7 = SCAN r6 OUTPUT (In.1 ++ "app/views/" ++ In.2), In.0

          1250   ~0%    {2} r8 = r2 UNION r7
           581   ~0%    {2} r9 = JOIN r8 WITH FileSystem#df18ed9a::Make#FileSystem#e91ad87f::Input#::Container::getRelativePath#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1
          3243   ~0%    {2} r10 = JOIN r9 WITH containerparent ON FIRST 1 OUTPUT Rhs.1, Lhs.1
          2767   ~0%    {2} r11 = JOIN r10 WITH Erb#b2b9e6ed::ErbFile#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.0

          1236   ~1%    {3} r12 = SCAN r1 OUTPUT In.0, "", In.1

          1250   ~1%    {3} r13 = r12 UNION r6
        102500   ~0%    {4} r14 = JOIN r13 WITH project#ActionController#32b59475::getErbFileRelativePath#1#ff CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0, Lhs.1, Lhs.2
        102500   ~0%    {5} r15 = JOIN r14 WITH ActionController#32b59475::getErbFileRelativePath#1#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.0
        102500   ~0%    {4} r16 = JOIN r15 WITH Erb#b2b9e6ed::ErbFile#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.4, Lhs.0, (Lhs.2 ++ "app/views/layouts/" ++ Lhs.3 ++ "%")
            41   ~0%    {4} r17 = SELECT r16 ON In.1 matches In.3
            41   ~3%    {2} r18 = SCAN r17 OUTPUT In.0, In.2

          2808   ~1%    {2} r19 = r11 UNION r18
                        return r19
```
2023-04-25 21:04:30 +02:00
Rasmus Wriedt Larsen
95b8a22529 Merge pull request #12889 from kaspersv/kaspersv/prevent-python-join-order-regression
Prevent Python join order regression
2023-04-25 18:02:13 +02:00
Óscar San José
a95fc79874 Merge branch 'main' into sabrowning1/query-suite-name-fix 2023-04-25 16:57:26 +02:00
Ed Minnix
d98723c35a Fix naming of OkHttpFlowConfig in test 2023-04-25 10:31:27 -04:00
Jami
cff7f63193 Merge pull request #12838 from jcogs33/jcogs33/add-class-for-callables-interesting-for-modeling
Java: add class that represents callables that are interesting for MaD models
2023-04-25 09:28:56 -04:00
Alexandre Boulgakov
909f40b6ea Merge pull request #12918 from github/sashabu/absl
Swift: Fix some TODOs with Abseil.
2023-04-25 14:05:12 +01:00
Geoffrey White
84ddfe9c3f Merge pull request #12919 from geoffw0/precision2
Swift: Upgrade two queries to precision high.
2023-04-25 14:04:52 +01:00
Geoffrey White
b1712d33fe Merge pull request #12837 from geoffw0/flowsources
Swift: widen swift/predicate-injection sources
2023-04-25 14:03:58 +01:00
yoff
b35637e1c5 Merge pull request #12858 from RasmusWL/paramiko-modeling
Python: Expand modeling of `paramiko`
2023-04-25 14:04:50 +02:00
Tony Torralba
89ee2b9ace Merge pull request #12911 from atorralba/atorralba/java/filecopyutils-file-sinks
Java: Fix FileCopyUtils.copy models
2023-04-25 12:06:13 +02:00
Asger F
c3c3faa4b5 JS: Alias references are not always safe to expand 2023-04-25 11:27:40 +02:00
Asger F
3694ed5ed6 JS: Deduplicate union/intersection members 2023-04-25 11:27:40 +02:00
Asger F
cab76507e7 JS: Recognize type vars on anonymous function types 2023-04-25 11:27:40 +02:00
Asger F
ff67118097 JS: Add hanging test case 2023-04-25 11:27:40 +02:00
Alex Denisov
125aab8107 Swift: rework fetching and dispatching
* visiting now happens in a later stage than fetching labels. While
  fetching a list of entities to be visited is created, and then acted
  upon in actual extraction. This partially flattens the recursive
  nature of `fetchLabel` into a loop inside `SwiftVisitor::extract`.
  Recursion in `fetchLabel` will only happen on labels fetched while
  naming an entity (calling into `SwiftMangler`).
* The choice whether to name a declaration or type has been moved from
  the translators to `SwiftMangler`. Acting on this choice is contained
  in `SwiftDispatcher::createLabel`.
* The choice whether to emit a body of a declaration has been moved from
  `DeclTranslator` to the dispatcher. This choice is also contained in
  `SwiftDispatcher::createLabel`.
* The simple functionality of the `LabelStore` has been moved to the
  `SwiftDispatcher` as well.
2023-04-25 11:15:27 +02:00
Joe Farebrother
a9d34458de Merge pull request #12658 from joefarebrother/csharp-sensitive-data
C#: Add local filesystem writes as External Location sinks
2023-04-25 10:14:48 +01:00
Geoffrey White
0ebb06e185 Merge branch 'main' into flowsources 2023-04-25 10:08:15 +01:00
Geoffrey White
2c28fae7e3 Merge pull request #12836 from geoffw0/precision
Swift: Downgrade swift/unsafe-js-eval to precision medium.
2023-04-25 09:58:11 +01:00
Geoffrey White
b0b2d6e05f Swift: Upgrade two queries to @precision high. 2023-04-25 09:42:49 +01:00
AlexDenisov
fcbd211783 Merge pull request #12910 from github/redsun82/swift-hash-lazy-trap-names
Swift: use hashing for lazy decl trap file names
2023-04-25 09:54:46 +02:00
Anders Schack-Mulligen
934a455908 Apply suggestions from code review
Update qldoc.
2023-04-25 09:35:26 +02:00
Tom Hvitved
65835cdb92 Merge pull request #12907 from hvitved/ruby/destructured-assign-join
Ruby: Fix bad join in `DestructuredAssignDesugar`
2023-04-25 08:50:27 +02:00
Alexandre Boulgakov
c88f9bf818 Swift: Use absl::StrJoin to dump arguments for logging.
This also removes the TODO about using `absl::StrJoin` to dump the environment because we can't easily get a range from a null-terminated `envp`. It also doesn't suffer from the usual awkwardness around inserting a separator *between* elements but not after the last one, so a for loop is clear enough.
2023-04-24 22:34:14 +01:00
Alexandre Boulgakov
621761b289 Swift: Use absl::bit_width to calculate TRAP label size.
It's not much cleaner due to arithmetic to convert truncating division to a ceiling, but has two advantages:
 1. It doesn't suffer from rounding issues with large TRAP labels. This is largely theoretical, but does let us handle `undefined` uniformly.
 2. It should be much faster (using LZCNT/BSR instead of floating point arithmetic). This is probably not a performance bottleneck, so *shrug*.
2023-04-24 22:31:11 +01:00
Ed Minnix
3af72fa28e Remove legacy code from InlineFlowTest 2023-04-24 17:10:32 -04:00
Ed Minnix
59e59125d6 Refactor tests 2023-04-24 17:10:32 -04:00
Alexandre Boulgakov
36d34f199b Bazel: Add Abseil C++ dependency. 2023-04-24 21:59:57 +01:00
Henry Mercer
3d1da8a45d JS: Update message when the file is not located in the source root 2023-04-24 21:08:00 +01:00
Henry Mercer
927522c563 JS: Only populate diagnostic locations within the source root 2023-04-24 20:53:42 +01:00
Owen Mansel-Chan
b47c8e8c4c Merge pull request #12912 from owen-mc/go/fix-invalid-semver-version
Go: Fix invalid SemVer version by adding "v" to the front
2023-04-24 16:47:28 +01:00
Sam Browning
0a7e525c16 Update "code-scanning" suite name to "default" 2023-04-24 11:27:34 -04:00
Paolo Tranquilli
14706b42fa Swift: strip parameters from lazy function decl trap names 2023-04-24 17:04:41 +02:00
Joe Farebrother
0ebf529dc4 Add comment + use flowTo 2023-04-24 15:49:05 +01:00
Michael Nebel
8756c031e0 C#: Re-factor the InappropriateEncoding query to use the new API. 2023-04-24 16:06:07 +02:00
Owen Mansel-Chan
1afe845ed3 Add missing "v" to semver version string
Because it was missing, that function always returned +1,
so we were doing the wrong thing when the Go version
installed was lower than 1.16.
2023-04-24 14:31:46 +01:00
Tony Torralba
e3d93c3581 Fix FileCopyUtils models 2023-04-24 15:07:19 +02:00
Paolo Tranquilli
e84bdf5bed Swift: use hashing for lazy decl trap file names
It turns out mangled names can sometimes be too long. While this code
will eventually be replaced by our own mangling, we need to use hashing
to cut down the names.

Module and decl names are preserved in the trap file names for
debuggability.
2023-04-24 14:36:36 +02:00
Paolo Tranquilli
feb31612f5 Merge pull request #12908 from github/revert-12760-redsun82/swift-logging-compiler
Revert "Swift: route compiler diagnostics through our log"
2023-04-24 14:31:18 +02:00
Paolo Tranquilli
95ef7fb3f1 Revert "Swift: route compiler diagnostics through our log" 2023-04-24 13:57:24 +02:00
Tom Hvitved
71cd973b42 Ruby: Fix bad join in DestructuredAssignDesugar
```
Evaluated relational algebra for predicate Synthesis#d9ff06b1::DestructuredAssignDesugar::LhsWithReceiver::getSynthKind#0#dispred#ff@0c55fb0w on iteration 4 running pipeline order_500000 with tuple counts:
                 0   ~0%    {2} r1 = JOIN Synthesis#d9ff06b1::ConstantWriteAccessKind#ff#prev_delta WITH Constant#c70e4e0a::ScopeResolutionConstantAccess::getName#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1
                 0   ~0%    {2} r2 = JOIN r1 WITH Constant#c70e4e0a::ScopeResolutionConstantAccess::getScopeExpr#0#dispred#ff#prev ON FIRST 1 OUTPUT Lhs.0, Lhs.1

                 0   ~0%    {4} r3 = JOIN Call#841c84e8::MethodCall::getMethodName#0#dispred#ff#prev_delta WITH Call#841c84e8::Call::getNumberOfArguments#0#dispred#ff#prev ON FIRST 1 OUTPUT Lhs.1, false, Rhs.1, Lhs.0
                 0   ~0%    {2} r4 = JOIN r3 WITH Synthesis#d9ff06b1::MethodCallKind#ffff#prev ON FIRST 3 OUTPUT Lhs.3, Rhs.3

                 0   ~0%    {2} r5 = r2 UNION r4

            336618   ~3%    {1} r6 = SCAN Constant#c70e4e0a::ScopeResolutionConstantAccess::getScopeExpr#0#dispred#ff#prev_delta OUTPUT In.0
            336618   ~0%    {2} r7 = JOIN r6 WITH Constant#c70e4e0a::ScopeResolutionConstantAccess::getName#0#dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.0
                 0   ~0%    {2} r8 = JOIN r7 WITH Synthesis#d9ff06b1::ConstantWriteAccessKind#ff#prev ON FIRST 1 OUTPUT Lhs.1, Rhs.1

                 0   ~0%    {3} r9 = SCAN Call#841c84e8::Call::getNumberOfArguments#0#dispred#ff#prev_delta OUTPUT false, In.1, In.0
                 0   ~0%    {3} r10 = JOIN r9 WITH Synthesis#d9ff06b1::MethodCallKind#ffff#reorder_1_2_0_3#prev ON FIRST 2 OUTPUT Lhs.2, Rhs.2, Rhs.3
                 0   ~0%    {2} r11 = JOIN r10 WITH Call#841c84e8::MethodCall::getMethodName#0#dispred#ff#prev ON FIRST 2 OUTPUT Lhs.0, Lhs.2

              2119   ~2%    {3} r12 = JOIN Synthesis#d9ff06b1::MethodCallKind#ffff#reorder_1_2_0_3#prev_delta WITH const_false ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3
        2657005103   ~5%    {3} r13 = JOIN r12 WITH Call#841c84e8::Call::getNumberOfArguments#0#dispred#ff#reorder_1_0#prev ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2
           1184200   ~0%    {2} r14 = JOIN r13 WITH Call#841c84e8::MethodCall::getMethodName#0#dispred#ff#prev ON FIRST 2 OUTPUT Lhs.0, Lhs.2

           1184200   ~0%    {2} r15 = r11 UNION r14
           1184200   ~0%    {2} r16 = r8 UNION r15
           1184200   ~0%    {2} r17 = r5 UNION r16
           1184200   ~0%    {2} r18 = r17 AND NOT Synthesis#d9ff06b1::DestructuredAssignDesugar::LhsWithReceiver::getSynthKind#0#dispred#ff#prev(Lhs.0, Lhs.1)
                            return r18
```
2023-04-24 13:44:18 +02:00
Kasper Svendsen
361b15b2c7 Merge branch 'main' into kaspersv/prevent-python-join-order-regression 2023-04-24 13:35:07 +02:00
Kasper Svendsen
bfe5db20a3 Merge pull request #12891 from kaspersv/kaspersv/prevent-ruby-join-regression2
Prevent Ruby join order regression
2023-04-24 13:27:33 +02:00
Edward Minnix III
ba4d326768 Merge pull request #12902 from egregius313/egregius313/java/dataflow/refactor-integration-tests
Java: Refactor Kotlin Integration tests to new DataFlow API
2023-04-24 06:51:40 -04:00
Michael Nebel
8ade7247a1 Merge pull request #12885 from michaelnebel/mergepathgraph3
Dataflow: Introduce param module for merging three path graphs.
2023-04-24 12:49:28 +02:00
Rasmus Wriedt Larsen
bfbbb5277d Merge pull request #12888 from lcartey/mcafee-trojan-fp
Update `SimpleXmlRpcServer.ql` to avoid incorrect detection as a trojan by Mcafee
2023-04-24 11:17:52 +02:00
Erik Krogh Kristensen
b0efff0110 Merge pull request #12904 from github/dependabot/cargo/ql/tracing-subscriber-0.3.17
Bump tracing-subscriber from 0.3.16 to 0.3.17 in /ql
2023-04-24 11:05:36 +02:00
Erik Krogh Kristensen
b16444dd22 Merge pull request #12903 from github/dependabot/cargo/ql/regex-1.8.1
Bump regex from 1.8.0 to 1.8.1 in /ql
2023-04-24 11:05:13 +02:00
dependabot[bot]
5e274c9664 Bump tracing-subscriber from 0.3.16 to 0.3.17 in /ql
Bumps [tracing-subscriber](https://github.com/tokio-rs/tracing) from 0.3.16 to 0.3.17.
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.16...tracing-subscriber-0.3.17)

---
updated-dependencies:
- dependency-name: tracing-subscriber
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 04:12:25 +00:00
dependabot[bot]
a5e919b6cb Bump regex from 1.8.0 to 1.8.1 in /ql
Bumps [regex](https://github.com/rust-lang/regex) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/commits/1.8.1)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 04:12:06 +00:00
Ed Minnix
19e6a9a1d3 Fix version of PathGraph used 2023-04-21 19:08:56 -04:00
Ed Minnix
40aed29858 Refactor Java Integration tests to new API 2023-04-21 18:22:28 -04:00
Arthur Baars
b919547e31 Add change note 2023-04-21 17:42:02 +02:00
Arthur Baars
bc44b9e4fb Python: update stats for YAML tables 2023-04-21 17:42:02 +02:00
Arthur Baars
c4a7353583 Python: upgrade/downgrade scripts 2023-04-21 17:42:02 +02:00
Arthur Baars
f61565cab1 Python: add YAML library 2023-04-21 17:42:02 +02:00
Arthur Baars
9c25c150a3 Python: add YAML dbscheme fragment 2023-04-21 17:42:02 +02:00
Joe Farebrother
a4d7570788 Add more sources 2023-04-21 14:23:01 +01:00
Joe Farebrother
9881fdfe27 Convert sources to MaD 2023-04-21 14:19:17 +01:00
Erik Krogh Kristensen
4bf03e7962 Merge pull request #12897 from github/dependabot/cargo/ql/regex-1.8.0
Bump regex from 1.7.3 to 1.8.0 in /ql
2023-04-21 12:57:33 +02:00
Asger F
f3b14e13b2 Merge pull request #12841 from asgerf/rb/api-graph-class-nodes
Ruby: add API node representing a module/class object
2023-04-21 10:59:51 +02:00
Michael Nebel
239a763ef9 Merge pull request #12845 from michaelnebel/csharp/xssrefactor
C#: Re-factor Xss to use the new data flow API.
2023-04-21 08:55:07 +02:00
dependabot[bot]
149753c052 Bump regex from 1.7.3 to 1.8.0 in /ql
Bumps [regex](https://github.com/rust-lang/regex) from 1.7.3 to 1.8.0.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/commits)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-21 04:03:04 +00:00
Jami Cogswell
85542638d7 Java: refactor CaptureModelsSpecific; resolve conflict for isInTestFile 2023-04-20 16:23:12 -04:00
Jami Cogswell
94f11029ee Java: refactor ExternalApi 2023-04-20 16:19:15 -04:00
Jami Cogswell
2ae4b646a0 Java: adjust genVsMan query test cases 2023-04-20 16:19:15 -04:00
Jami Cogswell
2ca8103a7e Java: remove isImplicitlyPublic predicate since not needed for this use-case 2023-04-20 16:19:15 -04:00
Jami Cogswell
5dbd11a584 Java: move veryPublic predicate 2023-04-20 16:19:15 -04:00
Jami Cogswell
fa1a6da60d Java: update genVsMan query test case 2023-04-20 16:19:15 -04:00
Jami Cogswell
7c72ece4a0 Java: update genVsMan coverage query to use ModelApi instead of DataFlowTargetApi 2023-04-20 16:19:15 -04:00
Jami Cogswell
9828ad0fc3 Java: add draft of class to represent callables we are interested in modeling 2023-04-20 16:19:15 -04:00
Jami Cogswell
2e76e12316 Java: add class and predicates to approximate an effectively public method 2023-04-20 16:19:15 -04:00
Nora Dimitrijević
1f861fda25 Merge pull request #12736 from d10c/swift/capture-flow
Swift: Closure Capture Helper APIs
2023-04-20 18:45:56 +02:00
Michael Nebel
0fdeeba46f C#: Re-refactor Xss to use the new API. 2023-04-20 18:38:15 +02:00
Edward Minnix III
76f8d460e7 Merge pull request #12851 from egregius313/egregius313/mad/add-groovy-stubs-to-isInTestFile
Java: Add `*/test/*` to model generator's list of ignored paths
2023-04-20 11:06:38 -04:00
Paolo Tranquilli
00436828a9 Merge pull request #12883 from github/redsun82/swift-default-output-dir
Swift: aggregate default output directories
2023-04-20 16:58:31 +02:00
Kasper Svendsen
b707c8162e Prevent Ruby join order regression 2023-04-20 15:52:32 +02:00
Paolo Tranquilli
c7378a1e5b Merge branch 'main' into redsun82/swift-default-output-dir 2023-04-20 15:12:07 +02:00
Kasper Svendsen
603a97faf9 Prevent Python join order regression 2023-04-20 13:44:30 +02:00
Luke Cartey
9dc1ea1216 Merge branch 'main' into mcafee-trojan-fp 2023-04-20 12:34:38 +01:00
Luke Cartey
a47778c22e Update SimpleXmlRpcServer.ql to avoid av detection
This file was being flagged by McAfee as an `Exploit-Generic.src`
trojan. We have attempted to report this to Mcafee without success so
far. This commit therefore adjusts the file to avoid detection.
2023-04-20 11:59:18 +01:00
Michael Nebel
656d8d2451 Sync files. 2023-04-20 11:29:51 +02:00
Michael Nebel
c71278ceb7 C#: Introduce parameterized module for merging three path graphs. 2023-04-20 11:29:34 +02:00
Paolo Tranquilli
60c723e7cc Swift: aggregate default output directories
In case the extractor is run in isolation for debugging/testing, this
will avoid littering the current working directory with artifacts, and
instead having a single `extractor-out` directory to inspect or clean
up.

Also extractor logs have been nested into a `swift` directory, as the
log directory provided by the `codeql` cli is actually shared between
languages.
2023-04-20 09:20:11 +02:00
Edward Minnix III
fc3c776bdc Permit CodeQL's own tests
Removing `%/test/%` accidentally removed our own test cases.

Co-authored-by: Jami <57204504+jcogs33@users.noreply.github.com>
2023-04-18 15:31:49 -04:00
Nora Dimitrijević
7f675d8c3b Swift: more CapturedDecl test cases 2023-04-18 16:50:38 +02:00
Nora Dimitrijević
96f06f8eca Swift: refactor the public API wrt captures
This exposes capture- and access-related methods under different names.
2023-04-18 16:50:37 +02:00
Ed Minnix
83d5cde01d Change isInTestFile to ignore %/test/% 2023-04-18 10:27:20 -04:00
Rasmus Wriedt Larsen
a168af349e Python: Expand modeling of paramiko 2023-04-18 11:57:20 +02:00
Rasmus Wriedt Larsen
a5a0861be0 Python: Expand test of py/paramiko-missing-host-key-validation 2023-04-18 11:56:07 +02:00
Ed Minnix
d1de453c7a Change multiple match calls to set literal 2023-04-17 15:36:44 -04:00
Ed Minnix
027f08a0df Add groovy-stubs/test to list of directory names to ignore in model generator. 2023-04-17 14:34:04 -04:00
Asger F
e180b7e2ba Ruby: add locations for module object nodes 2023-04-17 12:49:35 +02:00
Asger F
8c0c335daf Ruby: update test output 2023-04-17 12:47:23 +02:00
Asger F
8363171f1f Ruby: Add MkModuleObject as API node for a module/class 2023-04-17 12:47:23 +02:00
Asger F
7332cec9a5 Ruby: fix missing 'self' parameters in ModuleNode.getAnImmediateReferenc 2023-04-17 12:47:23 +02:00
Asger F
29a20550f6 Ruby: use MkUse/MkDef for successors, use/def for predecessors 2023-04-17 12:47:23 +02:00
Geoffrey White
706fdce527 Swift: Downgrade swift/unsafe-js-eval to precision medium. 2023-04-14 18:16:16 +01:00
Geoffrey White
2adc4c0feb Swift: PredicatUpgrade predicate injection sources from RemoteFlowSource to FlowSource. Even local input should be in parameters rather than concatenated into the predicate. 2023-04-14 17:50:57 +01:00
Geoffrey White
7b8606d411 Swift: Delete unnecessary import. 2023-04-14 16:36:22 +01:00
Joe Farebrother
17cfd489ea Add change note 2023-04-05 14:28:49 +01:00
Joe Farebrother
8b08e6042c Update formatting 2023-04-05 14:22:55 +01:00
Joe Farebrother
37f1770623 Add unit tests for private information query 2023-04-05 13:57:23 +01:00
Joe Farebrother
941df4f274 Add test for cleartext storage 2023-04-05 13:57:23 +01:00
Joe Farebrother
cb2b2bc334 Add qldoc and remove redundant import 2023-04-05 13:57:23 +01:00
Joe Farebrother
92198e1af0 Add local file writes as external location sinks 2023-04-05 13:57:23 +01:00
239 changed files with 30861 additions and 21775 deletions

6
.gitignore vendored
View File

@@ -11,12 +11,6 @@
*/ql/test/**/*.actual
*/ql/test/**/go.sum
# upgrade/downgrade script tests projects and artifacts
**/upgrades/**/test/*.testproj
**/upgrades/**/test/*.actual
**/downgrades/**/test/*.testproj
**/downgrades/**/test/*.actual
# Visual studio temporaries, except a file used by QL4VS
.vs/*
!.vs/VSWorkspaceSettings.json

View File

@@ -361,3 +361,52 @@ module MergePathGraph<
}
}
}
/**
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
*/
module MergePathGraph3<
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
{
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
private module Merged =
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
class PathNode instanceof Merged::PathNode {
/** Gets this as a projection on the first given `PathGraph`. */
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
/** Gets this as a projection on the second given `PathGraph`. */
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
/** Gets this as a projection on the third given `PathGraph`. */
PathNode3 asPathNode3() { result = super.asPathNode2() }
/** Gets a textual representation of this element. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
Node getNode() { result = super.getNode() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph = Merged::PathGraph;
}

View File

@@ -361,3 +361,52 @@ module MergePathGraph<
}
}
}
/**
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
*/
module MergePathGraph3<
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
{
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
private module Merged =
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
class PathNode instanceof Merged::PathNode {
/** Gets this as a projection on the first given `PathGraph`. */
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
/** Gets this as a projection on the second given `PathGraph`. */
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
/** Gets this as a projection on the third given `PathGraph`. */
PathNode3 asPathNode3() { result = super.asPathNode2() }
/** Gets a textual representation of this element. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
Node getNode() { result = super.getNode() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph = Merged::PathGraph;
}

View File

@@ -34,9 +34,13 @@ private module Cached {
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldInstruction oldInstruction |
exists(OldIR::Instruction oldInstruction |
irFunc = oldInstruction.getEnclosingIRFunction() and
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
(
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
or
oldInstruction.getOpcode() instanceof Opcode::Unreached
)
)
}
@@ -366,21 +370,19 @@ private module Cached {
then
result = getChi(getOldInstruction(instruction)) and
kind instanceof GotoEdge
else (
else
exists(OldInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
(
oldInstruction = getOldInstruction(instruction)
or
instruction = getChi(oldInstruction)
) and
(
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
)
)
or
exists(OldInstruction oldInstruction |
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction.getSuccessor(kind))
)
)
}
cached

View File

@@ -19,6 +19,9 @@ newtype TInstruction =
) {
IRConstruction::Raw::hasInstruction(tag1, tag2)
} or
TRawUnreachedInstruction(IRFunctionBase irFunc) {
IRConstruction::hasUnreachedInstruction(irFunc)
} or
TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) {

View File

@@ -171,9 +171,9 @@ module Raw {
}
}
class TStageInstruction = TRawInstruction;
class TStageInstruction = TRawInstruction or TRawUnreachedInstruction;
predicate hasInstruction(TRawInstruction instr) { any() }
predicate hasInstruction(TStageInstruction instr) { any() }
predicate hasModeledMemoryResult(Instruction instruction) { none() }
@@ -361,6 +361,11 @@ private predicate isStrictlyForwardGoto(GotoStmt goto) {
Locatable getInstructionAst(TStageInstruction instr) {
result = getInstructionTranslatedElement(instr).getAst()
or
exists(IRFunction irFunc |
instr = TRawUnreachedInstruction(irFunc) and
result = irFunc.getFunction()
)
}
/** DEPRECATED: Alias for getInstructionAst */
@@ -370,14 +375,22 @@ deprecated Locatable getInstructionAST(TStageInstruction instr) {
CppType getInstructionResultType(TStageInstruction instr) {
getInstructionTranslatedElement(instr).hasInstruction(_, getInstructionTag(instr), result)
or
instr instanceof TRawUnreachedInstruction and
result = getVoidType()
}
predicate getInstructionOpcode(Opcode opcode, TStageInstruction instr) {
getInstructionTranslatedElement(instr).hasInstruction(opcode, getInstructionTag(instr), _)
or
instr instanceof TRawUnreachedInstruction and
opcode instanceof Opcode::Unreached
}
IRFunctionBase getInstructionEnclosingIRFunction(TStageInstruction instr) {
result.getFunction() = getInstructionTranslatedElement(instr).getFunction()
or
instr = TRawUnreachedInstruction(result)
}
Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction) {
@@ -386,6 +399,16 @@ Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction
.getPrimaryInstructionForSideEffect(getInstructionTag(instruction))
}
predicate hasUnreachedInstruction(IRFunction func) {
exists(Call c |
c.getEnclosingFunction() = func.getFunction() and
any(Options opt).exits(c.getTarget())
) and
not exists(TranslatedUnreachableReturnStmt return |
return.getEnclosingFunction().getFunction() = func.getFunction()
)
}
import CachedForDebugging
cached

View File

@@ -34,6 +34,7 @@ newtype TInstructionTag =
CallTargetTag() or
CallTag() or
CallSideEffectTag() or
CallNoReturnTag() or
AllocationSizeTag() or
AllocationElementSizeTag() or
AllocationExtentConvertTag() or

View File

@@ -8,6 +8,7 @@ private import SideEffects
private import TranslatedElement
private import TranslatedExpr
private import TranslatedFunction
private import DefaultOptions as DefaultOptions
/**
* Gets the `CallInstruction` from the `TranslatedCallExpr` for the specified expression.
@@ -66,7 +67,13 @@ abstract class TranslatedCall extends TranslatedExpr {
)
or
child = getSideEffects() and
result = getParent().getChildSuccessor(this)
if this.isNoReturn()
then
result =
any(UnreachedInstruction instr |
this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction()
)
else result = this.getParent().getChildSuccessor(this)
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -161,6 +168,8 @@ abstract class TranslatedCall extends TranslatedExpr {
*/
abstract predicate hasArguments();
predicate isNoReturn() { none() }
final TranslatedSideEffects getSideEffects() { result.getExpr() = expr }
}
@@ -266,6 +275,8 @@ abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedC
}
final override int getNumberOfArguments() { result = expr.getNumberOfArguments() }
final override predicate isNoReturn() { any(Options opt).exits(expr.getTarget()) }
}
/**

View File

@@ -7,6 +7,9 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
)
or
instr.getSuccessor(kind) instanceof UnreachedInstruction and
kind instanceof GotoEdge
}
pragma[noinline]
@@ -41,7 +44,9 @@ class ReachableBlock extends IRBlockBase {
* An instruction that is contained in a reachable block.
*/
class ReachableInstruction extends Instruction {
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
ReachableInstruction() {
this.getBlock() instanceof ReachableBlock and not this instanceof UnreachedInstruction
}
}
module Graph {

View File

@@ -34,9 +34,13 @@ private module Cached {
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldInstruction oldInstruction |
exists(OldIR::Instruction oldInstruction |
irFunc = oldInstruction.getEnclosingIRFunction() and
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
(
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
or
oldInstruction.getOpcode() instanceof Opcode::Unreached
)
)
}
@@ -366,21 +370,19 @@ private module Cached {
then
result = getChi(getOldInstruction(instruction)) and
kind instanceof GotoEdge
else (
else
exists(OldInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
(
oldInstruction = getOldInstruction(instruction)
or
instruction = getChi(oldInstruction)
) and
(
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
)
)
or
exists(OldInstruction oldInstruction |
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction.getSuccessor(kind))
)
)
}
cached

View File

@@ -7,6 +7,9 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
)
or
instr.getSuccessor(kind) instanceof UnreachedInstruction and
kind instanceof GotoEdge
}
pragma[noinline]
@@ -41,7 +44,9 @@ class ReachableBlock extends IRBlockBase {
* An instruction that is contained in a reachable block.
*/
class ReachableInstruction extends Instruction {
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
ReachableInstruction() {
this.getBlock() instanceof ReachableBlock and not this instanceof UnreachedInstruction
}
}
module Graph {

View File

@@ -1,10 +0,0 @@
--- old/aggregate_array_init
+++ new/aggregate_array_init
-| 0 | 3 | 42 |
+| 0 | 3 | 42 | 17 |
--- old/aggregate_field_init
+++ new/aggregate_field_init
-| 0 | 1 | 2 |
+| 0 | 1 | 2 | 3 |

View File

@@ -1,15 +0,0 @@
aggregate_field_init(@"an_aggregate_literal", @"init1", @"a_field")
aggregate_array_init(@"an_aggregate_literal", @"init2", 42)
files(@"file", "dummy file")
locations_expr(@"loc", @"file", 0, 0, 0, 0)
exprs(@"an_aggregate_literal", 127, @"loc")
exprs(@"init1", 1, @"loc")
exprs(@"init2", 1, @"loc")
membervariables(@"a_field", @"a_type", "my_field")
usertypes(@"a_type", "MyType", 1)
exprparents(@"init1", 3, @"an_aggregate_literal")
exprparents(@"init2", 17, @"an_aggregate_literal")

View File

@@ -14377,6 +14377,60 @@ ir.cpp:
# 1885| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
# 1885| ValueCategory = lvalue
# 1886| getStmt(2): [ReturnStmt] return ...
# 1889| [TopLevelFunction] void noreturnFunc()
# 1889| <params>:
# 1891| [TopLevelFunction] int noreturnTest(int)
# 1891| <params>:
# 1891| getParameter(0): [Parameter] x
# 1891| Type = [IntType] int
# 1891| getEntryPoint(): [BlockStmt] { ... }
# 1892| getStmt(0): [IfStmt] if (...) ...
# 1892| getCondition(): [LTExpr] ... < ...
# 1892| Type = [BoolType] bool
# 1892| ValueCategory = prvalue
# 1892| getLesserOperand(): [VariableAccess] x
# 1892| Type = [IntType] int
# 1892| ValueCategory = prvalue(load)
# 1892| getGreaterOperand(): [Literal] 10
# 1892| Type = [IntType] int
# 1892| Value = [Literal] 10
# 1892| ValueCategory = prvalue
# 1892| getThen(): [BlockStmt] { ... }
# 1893| getStmt(0): [ReturnStmt] return ...
# 1893| getExpr(): [VariableAccess] x
# 1893| Type = [IntType] int
# 1893| ValueCategory = prvalue(load)
# 1894| getElse(): [BlockStmt] { ... }
# 1895| getStmt(0): [ExprStmt] ExprStmt
# 1895| getExpr(): [FunctionCall] call to noreturnFunc
# 1895| Type = [VoidType] void
# 1895| ValueCategory = prvalue
# 1897| getStmt(1): [ReturnStmt] return ...
# 1899| [TopLevelFunction] int noreturnTest2(int)
# 1899| <params>:
# 1899| getParameter(0): [Parameter] x
# 1899| Type = [IntType] int
# 1899| getEntryPoint(): [BlockStmt] { ... }
# 1900| getStmt(0): [IfStmt] if (...) ...
# 1900| getCondition(): [LTExpr] ... < ...
# 1900| Type = [BoolType] bool
# 1900| ValueCategory = prvalue
# 1900| getLesserOperand(): [VariableAccess] x
# 1900| Type = [IntType] int
# 1900| ValueCategory = prvalue(load)
# 1900| getGreaterOperand(): [Literal] 10
# 1900| Type = [IntType] int
# 1900| Value = [Literal] 10
# 1900| ValueCategory = prvalue
# 1900| getThen(): [BlockStmt] { ... }
# 1901| getStmt(0): [ExprStmt] ExprStmt
# 1901| getExpr(): [FunctionCall] call to noreturnFunc
# 1901| Type = [VoidType] void
# 1901| ValueCategory = prvalue
# 1903| getStmt(1): [ReturnStmt] return ...
# 1903| getExpr(): [VariableAccess] x
# 1903| Type = [IntType] int
# 1903| ValueCategory = prvalue(load)
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -1886,4 +1886,21 @@ namespace missing_declaration_entries {
}
}
[[noreturn]] void noreturnFunc();
int noreturnTest(int x) {
if (x < 10) {
return x;
} else {
noreturnFunc();
}
}
int noreturnTest2(int x) {
if (x < 10) {
noreturnFunc();
}
return x;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -8741,6 +8741,44 @@
| ir.cpp:1885:11:1885:50 | ChiPartial | partial:m1885_4 |
| ir.cpp:1885:11:1885:50 | ChiTotal | total:m1883_4 |
| ir.cpp:1885:11:1885:50 | SideEffect | ~m1883_4 |
| ir.cpp:1891:5:1891:16 | Address | &:r1891_7 |
| ir.cpp:1891:5:1891:16 | ChiPartial | partial:m1891_3 |
| ir.cpp:1891:5:1891:16 | ChiTotal | total:m1891_2 |
| ir.cpp:1891:5:1891:16 | Load | m1893_4 |
| ir.cpp:1891:5:1891:16 | SideEffect | m1891_3 |
| ir.cpp:1891:22:1891:22 | Address | &:r1891_5 |
| ir.cpp:1892:9:1892:9 | Address | &:r1892_1 |
| ir.cpp:1892:9:1892:9 | Left | r1892_2 |
| ir.cpp:1892:9:1892:9 | Load | m1891_6 |
| ir.cpp:1892:9:1892:14 | Condition | r1892_4 |
| ir.cpp:1892:13:1892:14 | Right | r1892_3 |
| ir.cpp:1893:9:1893:17 | Address | &:r1893_1 |
| ir.cpp:1893:16:1893:16 | Address | &:r1893_2 |
| ir.cpp:1893:16:1893:16 | Load | m1891_6 |
| ir.cpp:1893:16:1893:16 | StoreValue | r1893_3 |
| ir.cpp:1895:9:1895:20 | CallTarget | func:r1895_1 |
| ir.cpp:1895:9:1895:20 | ChiPartial | partial:m1895_3 |
| ir.cpp:1895:9:1895:20 | ChiTotal | total:m1891_4 |
| ir.cpp:1895:9:1895:20 | SideEffect | ~m1891_4 |
| ir.cpp:1899:5:1899:17 | Address | &:r1899_8 |
| ir.cpp:1899:5:1899:17 | ChiPartial | partial:m1899_3 |
| ir.cpp:1899:5:1899:17 | ChiTotal | total:m1899_2 |
| ir.cpp:1899:5:1899:17 | Load | m1903_4 |
| ir.cpp:1899:5:1899:17 | SideEffect | m1899_3 |
| ir.cpp:1899:23:1899:23 | Address | &:r1899_5 |
| ir.cpp:1900:9:1900:9 | Address | &:r1900_1 |
| ir.cpp:1900:9:1900:9 | Left | r1900_2 |
| ir.cpp:1900:9:1900:9 | Load | m1899_6 |
| ir.cpp:1900:9:1900:14 | Condition | r1900_4 |
| ir.cpp:1900:13:1900:14 | Right | r1900_3 |
| ir.cpp:1901:9:1901:20 | CallTarget | func:r1901_1 |
| ir.cpp:1901:9:1901:20 | ChiPartial | partial:m1901_3 |
| ir.cpp:1901:9:1901:20 | ChiTotal | total:m1899_4 |
| ir.cpp:1901:9:1901:20 | SideEffect | ~m1899_4 |
| ir.cpp:1903:5:1903:13 | Address | &:r1903_1 |
| ir.cpp:1903:12:1903:12 | Address | &:r1903_2 |
| ir.cpp:1903:12:1903:12 | Load | m1899_6 |
| ir.cpp:1903:12:1903:12 | StoreValue | r1903_3 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -10035,6 +10035,68 @@ ir.cpp:
# 1883| v1883_5(void) = AliasedUse : ~m?
# 1883| v1883_6(void) = ExitFunction :
# 1891| int noreturnTest(int)
# 1891| Block 0
# 1891| v1891_1(void) = EnterFunction :
# 1891| mu1891_2(unknown) = AliasedDefinition :
# 1891| mu1891_3(unknown) = InitializeNonLocal :
# 1891| r1891_4(glval<int>) = VariableAddress[x] :
# 1891| mu1891_5(int) = InitializeParameter[x] : &:r1891_4
# 1892| r1892_1(glval<int>) = VariableAddress[x] :
# 1892| r1892_2(int) = Load[x] : &:r1892_1, ~m?
# 1892| r1892_3(int) = Constant[10] :
# 1892| r1892_4(bool) = CompareLT : r1892_2, r1892_3
# 1892| v1892_5(void) = ConditionalBranch : r1892_4
#-----| False -> Block 2
#-----| True -> Block 1
# 1893| Block 1
# 1893| r1893_1(glval<int>) = VariableAddress[#return] :
# 1893| r1893_2(glval<int>) = VariableAddress[x] :
# 1893| r1893_3(int) = Load[x] : &:r1893_2, ~m?
# 1893| mu1893_4(int) = Store[#return] : &:r1893_1, r1893_3
# 1891| r1891_6(glval<int>) = VariableAddress[#return] :
# 1891| v1891_7(void) = ReturnValue : &:r1891_6, ~m?
# 1891| v1891_8(void) = AliasedUse : ~m?
# 1891| v1891_9(void) = ExitFunction :
# 1895| Block 2
# 1895| r1895_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 1895| v1895_2(void) = Call[noreturnFunc] : func:r1895_1
# 1895| mu1895_3(unknown) = ^CallSideEffect : ~m?
# 1897| v1897_1(void) = Unreached :
# 1899| int noreturnTest2(int)
# 1899| Block 0
# 1899| v1899_1(void) = EnterFunction :
# 1899| mu1899_2(unknown) = AliasedDefinition :
# 1899| mu1899_3(unknown) = InitializeNonLocal :
# 1899| r1899_4(glval<int>) = VariableAddress[x] :
# 1899| mu1899_5(int) = InitializeParameter[x] : &:r1899_4
# 1900| r1900_1(glval<int>) = VariableAddress[x] :
# 1900| r1900_2(int) = Load[x] : &:r1900_1, ~m?
# 1900| r1900_3(int) = Constant[10] :
# 1900| r1900_4(bool) = CompareLT : r1900_2, r1900_3
# 1900| v1900_5(void) = ConditionalBranch : r1900_4
#-----| False -> Block 2
#-----| True -> Block 1
# 1901| Block 1
# 1901| r1901_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 1901| v1901_2(void) = Call[noreturnFunc] : func:r1901_1
# 1901| mu1901_3(unknown) = ^CallSideEffect : ~m?
# 1899| v1899_6(void) = Unreached :
# 1903| Block 2
# 1903| r1903_1(glval<int>) = VariableAddress[#return] :
# 1903| r1903_2(glval<int>) = VariableAddress[x] :
# 1903| r1903_3(int) = Load[x] : &:r1903_2, ~m?
# 1903| mu1903_4(int) = Store[#return] : &:r1903_1, r1903_3
# 1899| r1899_7(glval<int>) = VariableAddress[#return] :
# 1899| v1899_8(void) = ReturnValue : &:r1899_7, ~m?
# 1899| v1899_9(void) = AliasedUse : ~m?
# 1899| v1899_10(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -2091,3 +2091,69 @@ ssa.cpp:
# 417| v417_5(void) = ReturnVoid :
# 417| v417_6(void) = AliasedUse : m417_3
# 417| v417_7(void) = ExitFunction :
# 423| int noreturnTest(int)
# 423| Block 0
# 423| v423_1(void) = EnterFunction :
# 423| m423_2(unknown) = AliasedDefinition :
# 423| m423_3(unknown) = InitializeNonLocal :
# 423| m423_4(unknown) = Chi : total:m423_2, partial:m423_3
# 423| r423_5(glval<int>) = VariableAddress[x] :
# 423| m423_6(int) = InitializeParameter[x] : &:r423_5
# 424| r424_1(glval<int>) = VariableAddress[x] :
# 424| r424_2(int) = Load[x] : &:r424_1, m423_6
# 424| r424_3(int) = Constant[10] :
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
# 424| v424_5(void) = ConditionalBranch : r424_4
#-----| False -> Block 2
#-----| True -> Block 1
# 425| Block 1
# 425| r425_1(glval<int>) = VariableAddress[#return] :
# 425| r425_2(glval<int>) = VariableAddress[x] :
# 425| r425_3(int) = Load[x] : &:r425_2, m423_6
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
# 423| r423_7(glval<int>) = VariableAddress[#return] :
# 423| v423_8(void) = ReturnValue : &:r423_7, m425_4
# 423| v423_9(void) = AliasedUse : m423_3
# 423| v423_10(void) = ExitFunction :
# 427| Block 2
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| m427_3(unknown) = ^CallSideEffect : ~m423_4
# 427| m427_4(unknown) = Chi : total:m423_4, partial:m427_3
# 423| v423_11(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| m431_2(unknown) = AliasedDefinition :
# 431| m431_3(unknown) = InitializeNonLocal :
# 431| m431_4(unknown) = Chi : total:m431_2, partial:m431_3
# 431| r431_5(glval<int>) = VariableAddress[x] :
# 431| m431_6(int) = InitializeParameter[x] : &:r431_5
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_6
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| m433_3(unknown) = ^CallSideEffect : ~m431_4
# 433| m433_4(unknown) = Chi : total:m431_4, partial:m433_3
# 431| v431_7(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_6
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_8(glval<int>) = VariableAddress[#return] :
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
# 431| v431_10(void) = AliasedUse : m431_3
# 431| v431_11(void) = ExitFunction :

View File

@@ -2080,3 +2080,69 @@ ssa.cpp:
# 417| v417_5(void) = ReturnVoid :
# 417| v417_6(void) = AliasedUse : m417_3
# 417| v417_7(void) = ExitFunction :
# 423| int noreturnTest(int)
# 423| Block 0
# 423| v423_1(void) = EnterFunction :
# 423| m423_2(unknown) = AliasedDefinition :
# 423| m423_3(unknown) = InitializeNonLocal :
# 423| m423_4(unknown) = Chi : total:m423_2, partial:m423_3
# 423| r423_5(glval<int>) = VariableAddress[x] :
# 423| m423_6(int) = InitializeParameter[x] : &:r423_5
# 424| r424_1(glval<int>) = VariableAddress[x] :
# 424| r424_2(int) = Load[x] : &:r424_1, m423_6
# 424| r424_3(int) = Constant[10] :
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
# 424| v424_5(void) = ConditionalBranch : r424_4
#-----| False -> Block 2
#-----| True -> Block 1
# 425| Block 1
# 425| r425_1(glval<int>) = VariableAddress[#return] :
# 425| r425_2(glval<int>) = VariableAddress[x] :
# 425| r425_3(int) = Load[x] : &:r425_2, m423_6
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
# 423| r423_7(glval<int>) = VariableAddress[#return] :
# 423| v423_8(void) = ReturnValue : &:r423_7, m425_4
# 423| v423_9(void) = AliasedUse : m423_3
# 423| v423_10(void) = ExitFunction :
# 427| Block 2
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| m427_3(unknown) = ^CallSideEffect : ~m423_4
# 427| m427_4(unknown) = Chi : total:m423_4, partial:m427_3
# 423| v423_11(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| m431_2(unknown) = AliasedDefinition :
# 431| m431_3(unknown) = InitializeNonLocal :
# 431| m431_4(unknown) = Chi : total:m431_2, partial:m431_3
# 431| r431_5(glval<int>) = VariableAddress[x] :
# 431| m431_6(int) = InitializeParameter[x] : &:r431_5
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_6
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| m433_3(unknown) = ^CallSideEffect : ~m431_4
# 433| m433_4(unknown) = Chi : total:m431_4, partial:m433_3
# 431| v431_7(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_6
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_8(glval<int>) = VariableAddress[#return] :
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
# 431| v431_10(void) = AliasedUse : m431_3
# 431| v431_11(void) = ExitFunction :

View File

@@ -417,3 +417,20 @@ void vla(int n1, int n2, int n3, bool b1) {
void nested_array_designators() {
int x[1][2] = {[0][0] = 1234, [0][1] = 5678};
}
[[noreturn]] void noreturnFunc();
int noreturnTest(int x) {
if (x < 10) {
return x;
} else {
noreturnFunc();
}
}
int noreturnTest2(int x) {
if (x < 10) {
noreturnFunc();
}
return x;
}

View File

@@ -1940,3 +1940,65 @@ ssa.cpp:
# 417| v417_4(void) = ReturnVoid :
# 417| v417_5(void) = AliasedUse : ~m?
# 417| v417_6(void) = ExitFunction :
# 423| int noreturnTest(int)
# 423| Block 0
# 423| v423_1(void) = EnterFunction :
# 423| mu423_2(unknown) = AliasedDefinition :
# 423| mu423_3(unknown) = InitializeNonLocal :
# 423| r423_4(glval<int>) = VariableAddress[x] :
# 423| m423_5(int) = InitializeParameter[x] : &:r423_4
# 424| r424_1(glval<int>) = VariableAddress[x] :
# 424| r424_2(int) = Load[x] : &:r424_1, m423_5
# 424| r424_3(int) = Constant[10] :
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
# 424| v424_5(void) = ConditionalBranch : r424_4
#-----| False -> Block 2
#-----| True -> Block 1
# 425| Block 1
# 425| r425_1(glval<int>) = VariableAddress[#return] :
# 425| r425_2(glval<int>) = VariableAddress[x] :
# 425| r425_3(int) = Load[x] : &:r425_2, m423_5
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
# 423| r423_6(glval<int>) = VariableAddress[#return] :
# 423| v423_7(void) = ReturnValue : &:r423_6, m425_4
# 423| v423_8(void) = AliasedUse : ~m?
# 423| v423_9(void) = ExitFunction :
# 427| Block 2
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| mu427_3(unknown) = ^CallSideEffect : ~m?
# 423| v423_10(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| mu431_2(unknown) = AliasedDefinition :
# 431| mu431_3(unknown) = InitializeNonLocal :
# 431| r431_4(glval<int>) = VariableAddress[x] :
# 431| m431_5(int) = InitializeParameter[x] : &:r431_4
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_5
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| mu433_3(unknown) = ^CallSideEffect : ~m?
# 431| v431_6(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_5
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_7(glval<int>) = VariableAddress[#return] :
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
# 431| v431_9(void) = AliasedUse : ~m?
# 431| v431_10(void) = ExitFunction :

View File

@@ -1940,3 +1940,65 @@ ssa.cpp:
# 417| v417_4(void) = ReturnVoid :
# 417| v417_5(void) = AliasedUse : ~m?
# 417| v417_6(void) = ExitFunction :
# 423| int noreturnTest(int)
# 423| Block 0
# 423| v423_1(void) = EnterFunction :
# 423| mu423_2(unknown) = AliasedDefinition :
# 423| mu423_3(unknown) = InitializeNonLocal :
# 423| r423_4(glval<int>) = VariableAddress[x] :
# 423| m423_5(int) = InitializeParameter[x] : &:r423_4
# 424| r424_1(glval<int>) = VariableAddress[x] :
# 424| r424_2(int) = Load[x] : &:r424_1, m423_5
# 424| r424_3(int) = Constant[10] :
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
# 424| v424_5(void) = ConditionalBranch : r424_4
#-----| False -> Block 2
#-----| True -> Block 1
# 425| Block 1
# 425| r425_1(glval<int>) = VariableAddress[#return] :
# 425| r425_2(glval<int>) = VariableAddress[x] :
# 425| r425_3(int) = Load[x] : &:r425_2, m423_5
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
# 423| r423_6(glval<int>) = VariableAddress[#return] :
# 423| v423_7(void) = ReturnValue : &:r423_6, m425_4
# 423| v423_8(void) = AliasedUse : ~m?
# 423| v423_9(void) = ExitFunction :
# 427| Block 2
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| mu427_3(unknown) = ^CallSideEffect : ~m?
# 423| v423_10(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| mu431_2(unknown) = AliasedDefinition :
# 431| mu431_3(unknown) = InitializeNonLocal :
# 431| r431_4(glval<int>) = VariableAddress[x] :
# 431| m431_5(int) = InitializeParameter[x] : &:r431_4
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_5
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| mu433_3(unknown) = ^CallSideEffect : ~m?
# 431| v431_6(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_5
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_7(glval<int>) = VariableAddress[#return] :
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
# 431| v431_9(void) = AliasedUse : ~m?
# 431| v431_10(void) = ExitFunction :

View File

@@ -1,28 +1,28 @@
package,sink,source,summary,sink:code,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:html,sink:remote,sink:sql,sink:xss,source:file,source:local,source:remote,summary:taint,summary:value
Dapper,55,,,,,,,,,,55,,,,,,
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,28,,,,,,
Microsoft.CSharp,,,24,,,,,,,,,,,,,24,
Microsoft.EntityFrameworkCore,6,,,,,,,,,,6,,,,,,
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,15,
Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,,45,1
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,80,3
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,,62,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,12,
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,,16,
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,,13,2
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,,16,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,10,
Microsoft.Extensions.Logging,,,37,,,,,,,,,,,,,37,
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,8,
Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,,63,
Microsoft.Interop,,,27,,,,,,,,,,,,,27,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,1,
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,,4,
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,5,5
Microsoft.Win32,,,8,,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,,75,92,,,,,7,
System,65,8,12154,,8,8,9,,4,,33,3,1,3,4,10163,1991
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,
package,sink,source,summary,sink:code,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:html,sink:remote,sink:sql,sink:xss,source:file,source:file-write,source:local,source:remote,summary:taint,summary:value
Dapper,55,,,,,,,,,,55,,,,,,,
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,28,,,,,,,
Microsoft.CSharp,,,24,,,,,,,,,,,,,,24,
Microsoft.EntityFrameworkCore,6,,,,,,,,,,6,,,,,,,
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,15,
Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,,,45,1
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,,80,3
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,,,62,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,12,
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,,,16,
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,,,13,2
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,,,16,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,10,
Microsoft.Extensions.Logging,,,37,,,,,,,,,,,,,,37,
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,8,
Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,,,63,
Microsoft.Interop,,,27,,,,,,,,,,,,,,27,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,1,
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,,,4,
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,5,5
Microsoft.Win32,,,8,,,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,,75,92,,,,,,7,
System,65,25,12154,,8,8,9,,4,,33,3,1,17,3,4,10163,1991
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,
1 package sink source summary sink:code sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:html sink:remote sink:sql sink:xss source:file source:file-write source:local source:remote summary:taint summary:value
2 Dapper 55 55
3 JsonToItemsTaskFactory 7 7
4 Microsoft.ApplicationBlocks.Data 28 28
5 Microsoft.CSharp 24 24
6 Microsoft.EntityFrameworkCore 6 6
7 Microsoft.Extensions.Caching.Distributed 15 15
8 Microsoft.Extensions.Caching.Memory 46 45 1
9 Microsoft.Extensions.Configuration 83 80 3
10 Microsoft.Extensions.DependencyInjection 62 62
11 Microsoft.Extensions.DependencyModel 12 12
12 Microsoft.Extensions.FileProviders 16 16
13 Microsoft.Extensions.FileSystemGlobbing 15 13 2
14 Microsoft.Extensions.Hosting 17 16 1
15 Microsoft.Extensions.Http 10 10
16 Microsoft.Extensions.Logging 37 37
17 Microsoft.Extensions.Options 8 8
18 Microsoft.Extensions.Primitives 63 63
19 Microsoft.Interop 27 27
20 Microsoft.NET.Build.Tasks 1 1
21 Microsoft.NETCore.Platforms.BuildTasks 4 4
22 Microsoft.VisualBasic 10 5 5
23 Microsoft.Win32 8 8
24 MySql.Data.MySqlClient 48 48
25 Newtonsoft.Json 91 73 18
26 ServiceStack 194 7 27 75 92 7
27 System 65 8 25 12154 8 8 9 4 33 3 1 17 3 4 10163 1991
28 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",8,12154,65,7
System,"``System.*``, ``System``",25,12154,65,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,556,138,
Totals,,8,12717,397,7
Totals,,25,12717,397,7

View File

@@ -4,6 +4,23 @@ extensions:
extensible: sourceModel
data:
- ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file", "manual"]
- ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String)", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Boolean)", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Boolean,System.Text.Encoding)", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Boolean,System.Text.Encoding,System.Int32)", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Text.Encoding,System.IO.FileStreamOptions)", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.IO.FileStreamOptions)", "", "Argument[this]", "file-write", "manual"]
- ["System.IO", "File", False, "Open", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "File", False, "OpenWrite", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "File", False, "Create", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "File", False, "CreateText", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "File", False, "AppendText", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "FileInfo", False, "Open", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "FileInfo", False, "OpenWrite", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "FileInfo", False, "Create", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "FileInfo", False, "CreateText", "", "", "ReturnValue", "file-write", "manual"]
- ["System.IO", "FileInfo", False, "AppendText", "", "", "ReturnValue", "file-write", "manual"]
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel

View File

@@ -215,7 +215,7 @@ module ModelValidation {
)
or
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
not kind = ["local", "remote", "file"] and
not kind = ["local", "remote", "file", "file-write"] and
result = "Invalid kind \"" + kind + "\" in source model."
)
}

View File

@@ -361,3 +361,52 @@ module MergePathGraph<
}
}
}
/**
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
*/
module MergePathGraph3<
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
{
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
private module Merged =
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
class PathNode instanceof Merged::PathNode {
/** Gets this as a projection on the first given `PathGraph`. */
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
/** Gets this as a projection on the second given `PathGraph`. */
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
/** Gets this as a projection on the third given `PathGraph`. */
PathNode3 asPathNode3() { result = super.asPathNode2() }
/** Gets a textual representation of this element. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
Node getNode() { result = super.getNode() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph = Merged::PathGraph;
}

View File

@@ -18,12 +18,10 @@ private import semmle.code.csharp.dataflow.TaintTracking2
*/
predicate xssFlow(XssNode source, XssNode sink, string message) {
// standard taint-tracking
exists(
TaintTrackingConfiguration c, DataFlow2::PathNode sourceNode, DataFlow2::PathNode sinkNode
|
exists(XssTracking::PathNode sourceNode, XssTracking::PathNode sinkNode |
sourceNode = source.asDataFlowNode() and
sinkNode = sink.asDataFlowNode() and
c.hasFlowPath(sourceNode, sinkNode) and
XssTracking::flowPath(sourceNode, sinkNode) and
message =
"is written to HTML or JavaScript" +
any(string explanation |
@@ -45,7 +43,7 @@ predicate xssFlow(XssNode source, XssNode sink, string message) {
module PathGraph {
/** Holds if `(pred,succ)` is an edge in the graph of data flow path explanations. */
query predicate edges(XssNode pred, XssNode succ) {
exists(DataFlow2::PathNode a, DataFlow2::PathNode b | DataFlow2::PathGraph::edges(a, b) |
exists(XssTracking::PathNode a, XssTracking::PathNode b | XssTracking::PathGraph::edges(a, b) |
pred.asDataFlowNode() = a and
succ.asDataFlowNode() = b
)
@@ -56,7 +54,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(XssNode n, string key, string val) {
DataFlow2::PathGraph::nodes(n.asDataFlowNode(), key, val)
XssTracking::PathGraph::nodes(n.asDataFlowNode(), key, val)
or
xssFlow(n, n, _) and
key = "semmle.label" and
@@ -69,13 +67,13 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(XssNode arg, XssNode par, XssNode ret, XssNode out) {
DataFlow2::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(), ret.asDataFlowNode(),
out.asDataFlowNode())
XssTracking::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(),
ret.asDataFlowNode(), out.asDataFlowNode())
}
}
private newtype TXssNode =
TXssDataFlowNode(DataFlow2::PathNode node) or
TXssDataFlowNode(XssTracking::PathNode node) or
TXssAspNode(AspInlineMember m)
/**
@@ -90,21 +88,25 @@ class XssNode extends TXssNode {
/** Gets the location of this node. */
Location getLocation() { none() }
/** Gets the data flow node corresponding to this node, if any. */
DataFlow2::PathNode asDataFlowNode() { result = this.(XssDataFlowNode).getDataFlowNode() }
/**
* Gets the data flow node corresponding to this node, if any.
*/
XssTracking::PathNode asDataFlowNode() { result = this.(XssDataFlowNode).getDataFlowNode() }
/** Gets the ASP inline code element corresponding to this node, if any. */
AspInlineMember asAspInlineMember() { result = this.(XssAspNode).getAspInlineMember() }
}
/** A data flow node, viewed as an XSS flow node. */
/**
* A data flow node, viewed as an XSS flow node.
*/
class XssDataFlowNode extends TXssDataFlowNode, XssNode {
DataFlow2::PathNode node;
XssTracking::PathNode node;
XssDataFlowNode() { this = TXssDataFlowNode(node) }
/** Gets the data flow node corresponding to this node. */
DataFlow2::PathNode getDataFlowNode() { result = node }
XssTracking::PathNode getDataFlowNode() { result = node }
override string toString() { result = node.toString() }
@@ -136,9 +138,11 @@ abstract class Source extends DataFlow::Node { }
abstract class Sanitizer extends DataFlow::ExprNode { }
/**
* DEPRECATED: Use `XssTracking` instead.
*
* A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities.
*/
class TaintTrackingConfiguration extends TaintTracking2::Configuration {
deprecated class TaintTrackingConfiguration extends TaintTracking2::Configuration {
TaintTrackingConfiguration() { this = "XSSDataFlowConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -148,6 +152,29 @@ class TaintTrackingConfiguration extends TaintTracking2::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities.
*/
module XssTrackingConfig implements DataFlow::ConfigSig {
/**
* Holds if `source` is a relevant data flow source.
*/
predicate isSource(DataFlow::Node source) { source instanceof Source }
/**
* Holds if `sink` is a relevant data flow sink.
*/
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
/**
* Holds if data flow through `node` is prohibited. This completely removes
* `node` from the data flow graph.
*/
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
module XssTracking = TaintTracking::Global<XssTrackingConfig>;
/** A source of remote user input. */
private class RemoteSource extends Source instanceof RemoteFlowSource { }

View File

@@ -6,6 +6,7 @@ import csharp
private import Remote
private import semmle.code.csharp.commons.Loggers
private import semmle.code.csharp.frameworks.system.Web
private import semmle.code.csharp.frameworks.system.IO
private import semmle.code.csharp.dataflow.ExternalFlow
/**
@@ -63,3 +64,56 @@ class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink {
)
}
}
private predicate isFileWriteCall(Expr stream, Expr data) {
exists(MethodCall mc, Method m | mc.getTarget() = m.getAnOverrider*() |
m.hasQualifiedName("System.IO", "Stream", ["Write", "WriteAsync"]) and
stream = mc.getQualifier() and
data = mc.getArgument(0)
or
m.hasQualifiedName("System.IO", "TextWriter",
["Write", "WriteAsync", "WriteLine", "WriteLineAsync"]) and
stream = mc.getQualifier() and
data = mc.getArgument(0)
or
m.hasQualifiedName("System.Xml.Linq", "XDocument", ["Save", "SaveAsync"]) and
data = mc.getQualifier() and
stream = mc.getArgument(0)
)
}
/** A configuration for tracking flow from calls that open a file in write mode to methods that write to that file, excluding encrypted streams. */
private module LocalFileOutputStreamConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { sourceNode(src, "file-write") }
predicate isSink(DataFlow::Node sink) { isFileWriteCall(sink.asExpr(), _) }
predicate isBarrier(DataFlow::Node node) {
node.asExpr()
.(ObjectCreation)
.getObjectType()
.hasQualifiedName("System.Security.Cryptography", "CryptoStream")
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(ObjectCreation oc |
node2.asExpr() = oc and
node1.asExpr() = oc.getArgument(0) and
oc.getObjectType() instanceof SystemIOStreamWriterClass
)
}
}
private module LocalFileOutputStreamFlow = DataFlow::Global<LocalFileOutputStreamConfig>;
/**
* A write to the local filesystem.
*/
class LocalFileOutputSink extends ExternalLocationSink {
LocalFileOutputSink() {
exists(DataFlow::Node streamSink |
LocalFileOutputStreamFlow::flowTo(streamSink) and
isFileWriteCall(streamSink.asExpr(), this.asExpr())
)
}
}

View File

@@ -16,18 +16,21 @@ import csharp
import semmle.code.csharp.security.dataflow.flowsources.Stored
import semmle.code.csharp.security.dataflow.XSSQuery
import semmle.code.csharp.security.dataflow.XSSSinks
import semmle.code.csharp.dataflow.DataFlow2
import DataFlow2::PathGraph
import StoredXss::PathGraph
class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration {
override predicate isSource(DataFlow2::Node source) { source instanceof StoredFlowSource }
module StoredXssTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource }
predicate isSink = XssTrackingConfig::isSink/1;
predicate isBarrier = XssTrackingConfig::isBarrier/1;
}
from
StoredTaintTrackingConfiguration c, DataFlow2::PathNode source, DataFlow2::PathNode sink,
string explanation
module StoredXss = TaintTracking::Global<StoredXssTrackingConfig>;
from StoredXss::PathNode source, StoredXss::PathNode sink, string explanation
where
c.hasFlowPath(source, sink) and
StoredXss::flowPath(source, sink) and
if exists(sink.getNode().(Sink).explanation())
then explanation = " (" + sink.getNode().(Sink).explanation() + ")"
else explanation = ""

View File

@@ -20,57 +20,46 @@ import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjection
import semmle.code.csharp.security.dataflow.flowsinks.Html
import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirect
import semmle.code.csharp.security.Sanitizers
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2::PathGraph
import semmle.code.csharp.dataflow.TaintTracking2
import EncodingConfigurations::Flow::PathGraph
/**
* A configuration for specifying expressions that must be
* encoded, along with a set of potential valid encoded values.
*/
abstract class RequiresEncodingConfiguration extends TaintTracking2::Configuration {
bindingset[this]
RequiresEncodingConfiguration() { any() }
/** Gets a textual representation of this kind of encoding requirement. */
abstract string getKind();
/** Holds if `e` is an expression whose value must be encoded. */
abstract predicate requiresEncoding(Node n);
signature module EncodingConfigSig {
/** Holds if `n` is a node whose value must be encoded. */
predicate requiresEncoding(DataFlow::Node n);
/** Holds if `e` is a possible valid encoded value. */
predicate isPossibleEncodedValue(Expr e) { none() }
predicate isPossibleEncodedValue(Expr e);
}
/**
* Holds if `encodedValue` is a possibly ill-encoded value that reaches
* `sink`, where `sink` is an expression of kind `kind` that is required
* to be encoded.
*/
predicate hasWrongEncoding(PathNode encodedValue, PathNode sink, string kind) {
this.hasFlowPath(encodedValue, sink) and
kind = this.getKind()
}
override predicate isSource(Node source) {
/**
* A configuration for specifying expressions that must be encoded.
*/
module RequiresEncodingConfig<EncodingConfigSig EncodingConfig> implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// all encoded values that do not match this configuration are
// considered sources
exists(Expr e | e = source.asExpr() |
e instanceof EncodedValue and
not this.isPossibleEncodedValue(e)
not EncodingConfig::isPossibleEncodedValue(e)
)
}
override predicate isSink(Node sink) { this.requiresEncoding(sink) }
predicate isSink(DataFlow::Node sink) { EncodingConfig::requiresEncoding(sink) }
override predicate isSanitizer(Node sanitizer) { this.isPossibleEncodedValue(sanitizer.asExpr()) }
predicate isBarrier(DataFlow::Node sanitizer) {
EncodingConfig::isPossibleEncodedValue(sanitizer.asExpr())
}
override int fieldFlowBranchLimit() { result = 0 }
int fieldFlowBranchLimit() { result = 0 }
}
/** An encoded value, for example a call to `HttpServerUtility.HtmlEncode`. */
/** An encoded value, for example through a call to `HttpServerUtility.HtmlEncode`. */
class EncodedValue extends Expr {
EncodedValue() {
any(RequiresEncodingConfiguration c).isPossibleEncodedValue(this)
EncodingConfigurations::SqlExprEncodingConfig::isPossibleEncodedValue(this)
or
EncodingConfigurations::HtmlExprEncodingConfig::isPossibleEncodedValue(this)
or
EncodingConfigurations::UrlExprEncodingConfig::isPossibleEncodedValue(this)
or
this = any(SystemWebHttpUtility c).getAJavaScriptStringEncodeMethod().getACall()
or
@@ -86,18 +75,20 @@ class EncodedValue extends Expr {
}
module EncodingConfigurations {
module SqlExprEncodingConfig implements EncodingConfigSig {
predicate requiresEncoding(DataFlow::Node n) { n instanceof SqlInjection::Sink }
predicate isPossibleEncodedValue(Expr e) { none() }
}
/** An encoding configuration for SQL expressions. */
class SqlExpr extends RequiresEncodingConfiguration {
SqlExpr() { this = "SqlExpr" }
override string getKind() { result = "SQL expression" }
override predicate requiresEncoding(Node n) { n instanceof SqlInjection::Sink }
module SqlExprConfig implements DataFlow::ConfigSig {
import RequiresEncodingConfig<SqlExprEncodingConfig> as Super
// no override for `isPossibleEncodedValue` as SQL parameters should
// be used instead of explicit encoding
override predicate isSource(Node source) {
super.isSource(source)
predicate isSource(DataFlow::Node source) {
Super::isSource(source)
or
// consider quote-replacing calls as additional sources for
// SQL expressions (e.g., `s.Replace("\"", "\"\"")`)
@@ -107,32 +98,62 @@ module EncodingConfigurations {
mc.getArgument(0).getValue().regexpMatch("\"|'|`")
)
}
predicate isSink = Super::isSink/1;
predicate isBarrier = Super::isBarrier/1;
int fieldFlowBranchLimit() { result = Super::fieldFlowBranchLimit() }
}
module SqlExpr = TaintTracking::Global<SqlExprConfig>;
module HtmlExprEncodingConfig implements EncodingConfigSig {
predicate requiresEncoding(DataFlow::Node n) { n instanceof HtmlSink }
predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
}
/** An encoding configuration for HTML expressions. */
class HtmlExpr extends RequiresEncodingConfiguration {
HtmlExpr() { this = "HtmlExpr" }
module HtmlExprConfig = RequiresEncodingConfig<HtmlExprEncodingConfig>;
override string getKind() { result = "HTML expression" }
module HtmlExpr = TaintTracking::Global<HtmlExprConfig>;
override predicate requiresEncoding(Node n) { n instanceof HtmlSink }
module UrlExprEncodingConfig implements EncodingConfigSig {
predicate requiresEncoding(DataFlow::Node n) { n instanceof UrlRedirect::Sink }
override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
predicate isPossibleEncodedValue(Expr e) { e instanceof UrlSanitizedExpr }
}
/** An encoding configuration for URL expressions. */
class UrlExpr extends RequiresEncodingConfiguration {
UrlExpr() { this = "UrlExpr" }
module UrlExprConfig = RequiresEncodingConfig<UrlExprEncodingConfig>;
override string getKind() { result = "URL expression" }
module UrlExpr = TaintTracking::Global<UrlExprConfig>;
override predicate requiresEncoding(Node n) { n instanceof UrlRedirect::Sink }
module Flow =
DataFlow::MergePathGraph3<SqlExpr::PathNode, HtmlExpr::PathNode, UrlExpr::PathNode,
SqlExpr::PathGraph, HtmlExpr::PathGraph, UrlExpr::PathGraph>;
override predicate isPossibleEncodedValue(Expr e) { e instanceof UrlSanitizedExpr }
/**
* Holds if `encodedValue` is a possibly ill-encoded value that reaches
* `sink`, where `sink` is an expression of kind `kind` that is required
* to be encoded.
*/
predicate hasWrongEncoding(Flow::PathNode encodedValue, Flow::PathNode sink, string kind) {
SqlExpr::flowPath(encodedValue.asPathNode1(), sink.asPathNode1()) and
kind = "SQL expression"
or
HtmlExpr::flowPath(encodedValue.asPathNode2(), sink.asPathNode2()) and
kind = "HTML expression"
or
UrlExpr::flowPath(encodedValue.asPathNode3(), sink.asPathNode3()) and
kind = "URL expression"
}
}
from RequiresEncodingConfiguration c, PathNode encodedValue, PathNode sink, string kind
where c.hasWrongEncoding(encodedValue, sink, kind)
from
EncodingConfigurations::Flow::PathNode encodedValue, EncodingConfigurations::Flow::PathNode sink,
string kind
where EncodingConfigurations::hasWrongEncoding(encodedValue, sink, kind)
select sink.getNode(), encodedValue, sink, "This " + kind + " may include data from a $@.",
encodedValue.getNode(), "possibly inappropriately encoded value"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Additional sinks modelling writes to unencrypted local files have been added to `ExternalLocationSink`, used by the `cs/cleartext-storage` and `cs/exposure-of-sensitive-information` queries.

View File

@@ -19,6 +19,9 @@ newtype TInstruction =
) {
IRConstruction::Raw::hasInstruction(tag1, tag2)
} or
TRawUnreachedInstruction(IRFunctionBase irFunc) {
IRConstruction::hasUnreachedInstruction(irFunc)
} or
TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) {

View File

@@ -414,6 +414,8 @@ private module Cached {
}
}
predicate hasUnreachedInstruction(IRFunction func) { none() }
import CachedForDebugging
cached

View File

@@ -34,9 +34,13 @@ private module Cached {
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldInstruction oldInstruction |
exists(OldIR::Instruction oldInstruction |
irFunc = oldInstruction.getEnclosingIRFunction() and
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
(
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
or
oldInstruction.getOpcode() instanceof Opcode::Unreached
)
)
}
@@ -366,21 +370,19 @@ private module Cached {
then
result = getChi(getOldInstruction(instruction)) and
kind instanceof GotoEdge
else (
else
exists(OldInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
(
oldInstruction = getOldInstruction(instruction)
or
instruction = getChi(oldInstruction)
) and
(
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
)
)
or
exists(OldInstruction oldInstruction |
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction.getSuccessor(kind))
)
)
}
cached

View File

@@ -2,6 +2,8 @@ using System.Text;
using System.Web;
using System.Web.Security;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
public class ClearTextStorageHandler : IHttpHandler
{
@@ -24,6 +26,22 @@ public class ClearTextStorageHandler : IHttpHandler
logger.Warn(GetPassword());
// GOOD: Logging encrypted sensitive data
logger.Warn(Encode(GetPassword(), "Password"));
// BAD: Storing sensitive data in local file
using (var writeStream = File.Open("passwords.txt", FileMode.Create))
{
var writer = new StreamWriter(writeStream);
writer.Write(GetPassword());
writer.Close();
}
// GOOD: Storing encrypted sensitive data
using (var writeStream = File.Open("passwords.txt", FileMode.Create))
{
var writer = new StreamWriter(new CryptoStream(writeStream, GetEncryptor(), CryptoStreamMode.Write));
writer.Write(GetPassword());
writer.Close();
}
}
public string Encode(string value, string type)
@@ -31,6 +49,10 @@ public class ClearTextStorageHandler : IHttpHandler
return Encoding.UTF8.GetString(MachineKey.Protect(Encoding.UTF8.GetBytes(value), type));
}
public ICryptoTransform GetEncryptor(){
return null;
}
public string GetPassword()
{
return "password";

View File

@@ -1,20 +1,22 @@
edges
nodes
| CleartextStorage.cs:13:50:13:59 | access to field accountKey | semmle.label | access to field accountKey |
| CleartextStorage.cs:14:62:14:74 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:15:69:15:81 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | semmle.label | call to method GetAccountID |
| CleartextStorage.cs:24:21:24:33 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:72:21:72:33 | access to property Text | semmle.label | access to property Text |
| CleartextStorage.cs:73:21:73:29 | access to property Text | semmle.label | access to property Text |
| CleartextStorage.cs:74:21:74:29 | access to property Text | semmle.label | access to property Text |
| CleartextStorage.cs:15:50:15:59 | access to field accountKey | semmle.label | access to field accountKey |
| CleartextStorage.cs:16:62:16:74 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:17:69:17:81 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | semmle.label | call to method GetAccountID |
| CleartextStorage.cs:26:21:26:33 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:34:26:34:38 | call to method GetPassword | semmle.label | call to method GetPassword |
| CleartextStorage.cs:94:21:94:33 | access to property Text | semmle.label | access to property Text |
| CleartextStorage.cs:95:21:95:29 | access to property Text | semmle.label | access to property Text |
| CleartextStorage.cs:96:21:96:29 | access to property Text | semmle.label | access to property Text |
subpaths
#select
| CleartextStorage.cs:13:50:13:59 | access to field accountKey | CleartextStorage.cs:13:50:13:59 | access to field accountKey | CleartextStorage.cs:13:50:13:59 | access to field accountKey | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:13:50:13:59 | access to field accountKey | access to field accountKey |
| CleartextStorage.cs:14:62:14:74 | call to method GetPassword | CleartextStorage.cs:14:62:14:74 | call to method GetPassword | CleartextStorage.cs:14:62:14:74 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:14:62:14:74 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:15:69:15:81 | call to method GetPassword | CleartextStorage.cs:15:69:15:81 | call to method GetPassword | CleartextStorage.cs:15:69:15:81 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:15:69:15:81 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | call to method GetAccountID |
| CleartextStorage.cs:24:21:24:33 | call to method GetPassword | CleartextStorage.cs:24:21:24:33 | call to method GetPassword | CleartextStorage.cs:24:21:24:33 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:24:21:24:33 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:72:21:72:33 | access to property Text | CleartextStorage.cs:72:21:72:33 | access to property Text | CleartextStorage.cs:72:21:72:33 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:72:21:72:33 | access to property Text | access to property Text |
| CleartextStorage.cs:73:21:73:29 | access to property Text | CleartextStorage.cs:73:21:73:29 | access to property Text | CleartextStorage.cs:73:21:73:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:73:21:73:29 | access to property Text | access to property Text |
| CleartextStorage.cs:74:21:74:29 | access to property Text | CleartextStorage.cs:74:21:74:29 | access to property Text | CleartextStorage.cs:74:21:74:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:74:21:74:29 | access to property Text | access to property Text |
| CleartextStorage.cs:15:50:15:59 | access to field accountKey | CleartextStorage.cs:15:50:15:59 | access to field accountKey | CleartextStorage.cs:15:50:15:59 | access to field accountKey | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:15:50:15:59 | access to field accountKey | access to field accountKey |
| CleartextStorage.cs:16:62:16:74 | call to method GetPassword | CleartextStorage.cs:16:62:16:74 | call to method GetPassword | CleartextStorage.cs:16:62:16:74 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:16:62:16:74 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:17:69:17:81 | call to method GetPassword | CleartextStorage.cs:17:69:17:81 | call to method GetPassword | CleartextStorage.cs:17:69:17:81 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:17:69:17:81 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | call to method GetAccountID |
| CleartextStorage.cs:26:21:26:33 | call to method GetPassword | CleartextStorage.cs:26:21:26:33 | call to method GetPassword | CleartextStorage.cs:26:21:26:33 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:26:21:26:33 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:34:26:34:38 | call to method GetPassword | CleartextStorage.cs:34:26:34:38 | call to method GetPassword | CleartextStorage.cs:34:26:34:38 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:34:26:34:38 | call to method GetPassword | call to method GetPassword |
| CleartextStorage.cs:94:21:94:33 | access to property Text | CleartextStorage.cs:94:21:94:33 | access to property Text | CleartextStorage.cs:94:21:94:33 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:94:21:94:33 | access to property Text | access to property Text |
| CleartextStorage.cs:95:21:95:29 | access to property Text | CleartextStorage.cs:95:21:95:29 | access to property Text | CleartextStorage.cs:95:21:95:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:95:21:95:29 | access to property Text | access to property Text |
| CleartextStorage.cs:96:21:96:29 | access to property Text | CleartextStorage.cs:96:21:96:29 | access to property Text | CleartextStorage.cs:96:21:96:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:96:21:96:29 | access to property Text | access to property Text |

View File

@@ -1 +1 @@
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll {testdir}/../../../../resources/stubs/System.Windows.cs
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll /r:System.Security.Cryptography.dll {testdir}/../../../../resources/stubs/System.Windows.cs

View File

@@ -1,4 +1,6 @@
using System.Web;
using System.Security.Cryptography;
using System.IO;
public class Person
{
@@ -21,9 +23,29 @@ public class ExposureOfPrivateInformationHandler : IHttpHandler
ILogger logger = new ILogger();
logger.Warn(p.getTelephone());
// BAD: Storing sensitive data in unencrypted local file
using (var writeStream = File.Open("telephones.txt", FileMode.Create))
{
var writer = new StreamWriter(writeStream);
writer.Write(p.getTelephone());
writer.Close();
}
// GOOD: Storing encrypted sensitive data
using (var writeStream = File.Open("telephones.txt", FileMode.Create))
{
var writer = new StreamWriter(new CryptoStream(writeStream, GetEncryptor(), CryptoStreamMode.Write));
writer.Write(p.getTelephone());
writer.Close();
}
// GOOD: Don't write these values to sensitive locations in the first place
}
public ICryptoTransform GetEncryptor(){
return null;
}
public bool IsReusable
{
get

View File

@@ -1,12 +1,14 @@
edges
nodes
| ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | semmle.label | access to indexer |
| ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | semmle.label | call to method getTelephone |
| ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | semmle.label | call to method getTelephone |
| ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | semmle.label | access to property Text |
| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | semmle.label | access to indexer |
| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | semmle.label | call to method getTelephone |
| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | semmle.label | call to method getTelephone |
| ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | semmle.label | call to method getTelephone |
| ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | semmle.label | access to property Text |
subpaths
#select
| ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | access to indexer |
| ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | call to method getTelephone |
| ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | call to method getTelephone |
| ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | access to property Text |
| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | access to indexer |
| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | call to method getTelephone |
| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | call to method getTelephone |
| ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | call to method getTelephone |
| ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | access to property Text |

View File

@@ -1 +1 @@
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll ${testdir}/../../../resources/stubs/System.Windows.cs
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll /r:System.Security.Cryptography.dll ${testdir}/../../../resources/stubs/System.Windows.cs

View File

@@ -1,7 +1,7 @@
CodeQL query help
-----------------
View the query help for the queries included in the ``code-scanning``, ``security-extended``, and ``security-and-quality`` query suites for the languages supported by CodeQL.
View the query help for the queries included in the ``default``, ``security-extended``, and ``security-and-quality`` query suites for the languages supported by CodeQL.
- :doc:`CodeQL query help for C and C++ <cpp>`
- :doc:`CodeQL query help for C# <csharp>`
@@ -15,20 +15,20 @@ View the query help for the queries included in the ``code-scanning``, ``securit
.. pull-quote:: Information
Each query help article includes:
Each query help article includes:
- A summary of key metadata for the query.
- Information about which query suites the query is included in.
- A link to the query in the `CodeQL repository <https://github.com/github/codeql>`__.
- A description of the potential vulnerability that the query identifies and a recommendation for how to avoid introducing the problem to your code.
For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE coverage <codeql-cwe-coverage>`."
For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE coverage <codeql-cwe-coverage>`."
.. toctree::
:hidden:
:titlesonly:
cpp
csharp
go
@@ -37,4 +37,3 @@ For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE cove
python
ruby
codeql-cwe-coverage

View File

@@ -1,5 +1,5 @@
Visit the articles below to see the documentation for the queries included in the following query suites:
- ``code-scanning``: queries run by default in CodeQL code scanning on GitHub.
- ``security-extended``: queries from ``code-scanning``, plus extra security queries with slightly lower precision and severity.
- ``security-and-quality``: queries from ``code-scanning``, ``security-extended``, plus extra maintainability and reliability queries.
- ``default``: queries run by default in CodeQL code scanning on GitHub.
- ``security-extended``: queries from ``default``, plus extra security queries with slightly lower precision and severity.
- ``security-and-quality``: queries from ``default``, ``security-extended``, plus extra maintainability and reliability queries.

View File

@@ -318,7 +318,7 @@ func getNeedGopath(depMode DependencyInstallerMode, importpath string) bool {
func tryUpdateGoModAndGoSum(modMode ModMode, depMode DependencyInstallerMode) {
// Go 1.16 and later won't automatically attempt to update go.mod / go.sum during package loading, so try to update them here:
if modMode != ModVendor && depMode == GoGetWithModules && semver.Compare(getEnvGoSemVer(), "1.16") >= 0 {
if modMode != ModVendor && depMode == GoGetWithModules && semver.Compare(getEnvGoSemVer(), "v1.16") >= 0 {
// stat go.mod and go.sum
beforeGoModFileInfo, beforeGoModErr := os.Stat("go.mod")
if beforeGoModErr != nil {

View File

@@ -361,3 +361,52 @@ module MergePathGraph<
}
}
}
/**
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
*/
module MergePathGraph3<
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
{
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
private module Merged =
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
class PathNode instanceof Merged::PathNode {
/** Gets this as a projection on the first given `PathGraph`. */
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
/** Gets this as a projection on the second given `PathGraph`. */
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
/** Gets this as a projection on the third given `PathGraph`. */
PathNode3 asPathNode3() { result = super.asPathNode2() }
/** Gets a textual representation of this element. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
Node getNode() { result = super.getNode() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph = Merged::PathGraph;
}

View File

@@ -138,7 +138,7 @@ org.springframework.jndi,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.springframework.ldap,47,,,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,87,52
org.springframework.util,3,,142,,2,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,90,52
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,
org.springframework.web.client,13,3,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,3,,
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
1 package sink source summary sink:bean-validation sink:create-file sink:fragment-injection sink:groovy sink:header-splitting sink:information-leak sink:intent-start sink:jdbc-url sink:jexl sink:jndi-injection sink:ldap sink:logging sink:mvel sink:ognl-injection sink:open-url sink:pending-intent-sent sink:read-file sink:regex-use sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:set-hostname-verifier sink:sql sink:ssti sink:url-open-stream sink:url-redirect sink:write-file sink:xpath sink:xslt sink:xss source:android-external-storage-dir source:android-widget source:contentprovider source:remote summary:taint summary:value
138 org.springframework.ldap 47 33 14
139 org.springframework.security.web.savedrequest 6 6
140 org.springframework.ui 32 32
141 org.springframework.util 3 139 142 2 1 87 90 52
142 org.springframework.validation 13 13
143 org.springframework.web.client 13 3 13 3
144 org.springframework.web.context.request 8 8

View File

@@ -21,7 +21,7 @@ Java framework & library support
Java Standard Library,``java.*``,3,673,168,39,,,9,,,13
Java extensions,"``javax.*``, ``jakarta.*``",63,611,34,1,,4,,1,1,2
Kotlin Standard Library,``kotlin*``,,1843,16,11,,,,,,2
`Spring <https://spring.io/>`_,``org.springframework.*``,29,480,101,,,,19,14,,29
`Spring <https://spring.io/>`_,``org.springframework.*``,29,483,104,2,,,19,14,,29
Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.geogebra.web.full.main``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",75,813,506,26,,,18,18,,175
Totals,,232,9096,1951,172,6,10,113,33,1,355
Totals,,232,9099,1954,174,6,10,113,33,1,355

View File

@@ -3,22 +3,22 @@ import semmle.code.java.dataflow.TaintTracking
import TestUtilities.InlineExpectationsTest
private import semmle.code.java.dataflow.ExternalFlow
class Config extends TaintTracking::Configuration {
Config() { this = "Config" }
override predicate isSource(DataFlow::Node n) {
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) {
n.asExpr().(MethodAccess).getCallee().getName() = "source"
or
sourceNode(n, "kotlinMadFlowTest")
}
override predicate isSink(DataFlow::Node n) {
predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
or
sinkNode(n, "kotlinMadFlowTest")
}
}
module Flow = TaintTracking::Global<Config>;
class InlineFlowTest extends InlineExpectationsTest {
InlineFlowTest() { this = "HasFlowTest" }
@@ -26,7 +26,7 @@ class InlineFlowTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "flow" and
exists(DataFlow::Node sink, Config c | c.hasFlowTo(sink) |
exists(DataFlow::Node sink | Flow::flowTo(sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""

View File

@@ -19,18 +19,18 @@ query predicate superAccesses(
enclosingType = enclosingCallable.getDeclaringType()
}
class Config extends DataFlow::Configuration {
Config() { this = "testconfig" }
override predicate isSource(DataFlow::Node x) {
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node x) {
x.asExpr() instanceof IntegerLiteral and x.getEnclosingCallable().fromSource()
}
override predicate isSink(DataFlow::Node x) {
predicate isSink(DataFlow::Node x) {
x.asExpr().(Argument).getCall().getCallee().getName() = "sink"
}
}
from Config c, DataFlow::Node source, DataFlow::Node sink
where c.hasFlow(source, sink)
module Flow = DataFlow::Global<Config>;
from DataFlow::Node source, DataFlow::Node sink
where Flow::flow(source, sink)
select source, sink

View File

@@ -1,17 +1,17 @@
import java
import semmle.code.java.dataflow.DataFlow
import DataFlow::PathGraph
import Flow::PathGraph
class Config extends DataFlow::Configuration {
Config() { this = "Config" }
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n.asExpr().(StringLiteral).getValue() = "taint" }
override predicate isSource(DataFlow::Node n) { n.asExpr().(StringLiteral).getValue() = "taint" }
override predicate isSink(DataFlow::Node n) {
predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, Config c
where c.hasFlowPath(source, sink)
module Flow = DataFlow::Global<Config>;
from Flow::PathNode source, Flow::PathNode sink
where Flow::flowPath(source, sink)
select source, source, sink, "flow path"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added new flow steps for `java.util.StringJoiner`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Changed some models of Spring's `FileCopyUtils.copy` to be path injection sinks instead of summaries.

View File

@@ -338,8 +338,14 @@ extensions:
- ["java.util", "Stack", True, "peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["java.util", "Stack", True, "pop", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["java.util", "Stack", True, "push", "(Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringJoiner", False, "StringJoiner", "", "", "Argument[0..2]", "Argument[this]", "taint", "manual"]
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["java.util", "StringJoiner", False, "merge", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["java.util", "StringJoiner", False, "merge", "", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["java.util", "StringJoiner", False, "setEmptyValue", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["java.util", "StringJoiner", False, "setEmptyValue", "", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["java.util", "StringJoiner", False, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringTokenizer", False, "StringTokenizer", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["java.util", "StringTokenizer", False, "nextElement", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringTokenizer", False, "nextToken", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]

View File

@@ -1,4 +1,12 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sinkModel
data:
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(byte[],File)", "", "Argument[1]", "create-file", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(File,File)", "", "Argument[0]", "read-file", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(File,File)", "", "Argument[1]", "create-file", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel
@@ -42,7 +50,10 @@ extensions:
- ["org.springframework.util", "FastByteArrayOutputStream", False, "toByteArray", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["org.springframework.util", "FastByteArrayOutputStream", False, "write", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["org.springframework.util", "FastByteArrayOutputStream", False, "writeTo", "", "", "Argument[this]", "Argument[0]", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(byte[],OutputStream)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(InputStream,OutputStream)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(Reader,Writer)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(String,Writer)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copyToByteArray", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["org.springframework.util", "FileCopyUtils", False, "copyToString", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["org.springframework.util", "FileSystemUtils", False, "copyRecursively", "(java.io.File,java.io.File)", "", "Argument[0]", "Argument[1]", "taint", "manual"]

View File

@@ -340,6 +340,47 @@ class Callable extends StmtParent, Member, @callable {
}
}
/**
* Holds if the given type is public and, if it is a nested type, that all of
* its enclosing types are public as well.
*/
private predicate veryPublic(RefType t) {
t.isPublic() and
(
not t instanceof NestedType or
veryPublic(t.(NestedType).getEnclosingType())
)
}
/** A callable that is the same as its source declaration. */
class SrcCallable extends Callable {
SrcCallable() { this.isSourceDeclaration() }
/**
* Holds if this callable is effectively public in the sense that it can be
* called from outside the codebase. This means either a `public` callable on
* a sufficiently public type or a `protected` callable on a sufficiently
* public non-`final` type.
*/
predicate isEffectivelyPublic() {
exists(RefType t | t = this.getDeclaringType() |
this.isPublic() and veryPublic(t)
or
this.isProtected() and not t.isFinal() and veryPublic(t)
)
or
exists(SrcRefType tsub, Method m |
veryPublic(tsub) and
tsub.hasMethod(m, _) and
m.getSourceDeclaration() = this
|
this.isPublic()
or
this.isProtected() and not tsub.isFinal()
)
}
}
/** Gets the erasure of `t1` if it is a raw type, or `t1` itself otherwise. */
private Type eraseRaw(Type t1) {
if t1 instanceof RawType then result = t1.getErasure() else result = t1

View File

@@ -361,3 +361,52 @@ module MergePathGraph<
}
}
}
/**
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
*/
module MergePathGraph3<
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
{
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
private module Merged =
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
class PathNode instanceof Merged::PathNode {
/** Gets this as a projection on the first given `PathGraph`. */
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
/** Gets this as a projection on the second given `PathGraph`. */
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
/** Gets this as a projection on the third given `PathGraph`. */
PathNode3 asPathNode3() { result = super.asPathNode2() }
/** Gets a textual representation of this element. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
Node getNode() { result = super.getNode() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph = Merged::PathGraph;
}

View File

@@ -0,0 +1,77 @@
/** Provides classes and predicates for exclusions related to MaD models. */
import java
/** Holds if the given package `p` is a test package. */
pragma[nomagic]
private predicate isTestPackage(Package p) {
p.getName()
.matches([
"org.junit%", "junit.%", "org.mockito%", "org.assertj%",
"com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%",
"org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%",
"org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%",
"org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions",
"org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", "org.jboss.arquillian.testng%",
"org.testng%"
])
}
/**
* A test library.
*/
class TestLibrary extends RefType {
TestLibrary() { isTestPackage(this.getPackage()) }
}
/** Holds if the given file is a test file. */
private predicate isInTestFile(File file) {
file.getAbsolutePath().matches(["%/test/%", "%/guava-tests/%", "%/guava-testlib/%"]) and
not file.getAbsolutePath().matches("%/ql/test/%") // allows our test cases to work
}
/** Holds if the given compilation unit's package is a JDK internal. */
private predicate isJdkInternal(CompilationUnit cu) {
cu.getPackage().getName().matches("org.graalvm%") or
cu.getPackage().getName().matches("com.sun%") or
cu.getPackage().getName().matches("sun%") or
cu.getPackage().getName().matches("jdk%") or
cu.getPackage().getName().matches("java2d%") or
cu.getPackage().getName().matches("build.tools%") or
cu.getPackage().getName().matches("propertiesparser%") or
cu.getPackage().getName().matches("org.jcp%") or
cu.getPackage().getName().matches("org.w3c%") or
cu.getPackage().getName().matches("org.ietf.jgss%") or
cu.getPackage().getName().matches("org.xml.sax%") or
cu.getPackage().getName().matches("com.oracle%") or
cu.getPackage().getName().matches("org.omg%") or
cu.getPackage().getName().matches("org.relaxng%") or
cu.getPackage().getName() = "compileproperties" or
cu.getPackage().getName() = "transparentruler" or
cu.getPackage().getName() = "genstubs" or
cu.getPackage().getName() = "netscape.javascript" or
cu.getPackage().getName() = ""
}
/** Holds if the given callable is not worth modeling. */
predicate isUninterestingForModels(Callable c) {
isInTestFile(c.getCompilationUnit().getFile()) or
isJdkInternal(c.getCompilationUnit()) or
c instanceof MainMethod or
c instanceof StaticInitializer or
exists(FunctionalExpr funcExpr | c = funcExpr.asMethod()) or
c.getDeclaringType() instanceof TestLibrary or
c.(Constructor).isParameterless()
}
/**
* A class that represents all callables for which we might be
* interested in having a MaD model.
*/
class ModelApi extends SrcCallable {
ModelApi() {
this.fromSource() and
this.isEffectivelyPublic() and
not isUninterestingForModels(this)
}
}

View File

@@ -1,9 +1,9 @@
private import semmle.code.java.dataflow.FlowSummary
private import utils.modelgenerator.internal.CaptureModels
private import semmle.code.java.dataflow.internal.ModelExclusions
private import TopJdkApis
/**
* Returns the number of `DataFlowTargetApi`s with Summary MaD models
* Returns the number of `ModelApi`s with Summary MaD models
* for a given package and provenance.
*/
bindingset[package, apiSubset]
@@ -13,7 +13,7 @@ private int getNumMadModeledApis(string package, string provenance, string apiSu
count(SummarizedCallable sc |
callableSubset(sc.asCallable(), apiSubset) and
package = sc.asCallable().getCompilationUnit().getPackage().getName() and
sc.asCallable() instanceof DataFlowTargetApi and
sc.asCallable() instanceof ModelApi and
(
// "auto-only"
not sc.hasManualModel() and
@@ -34,12 +34,12 @@ private int getNumMadModeledApis(string package, string provenance, string apiSu
)
}
/** Returns the total number of `DataFlowTargetApi`s for a given package. */
/** Returns the total number of `ModelApi`s for a given package. */
private int getNumApis(string package, string apiSubset) {
result =
strictcount(DataFlowTargetApi dataFlowTargApi |
callableSubset(dataFlowTargApi, apiSubset) and
package = dataFlowTargApi.getCompilationUnit().getPackage().getName()
strictcount(ModelApi api |
callableSubset(api, apiSubset) and
package = api.getCompilationUnit().getPackage().getName()
)
}
@@ -70,7 +70,7 @@ predicate modelCoverageGenVsMan(
// calculate the total generated and total manual numbers
generated = generatedOnly + both and
manual = manualOnly + both and
// count the total number of `DataFlowTargetApi`s for each package
// count the total number of `ModelApi`s for each package
all = getNumApis(package, apiSubset) and
non = all - (generatedOnly + both + manualOnly) and
// Proportion of coverage

View File

@@ -8,27 +8,7 @@ private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.internal.DataFlowPrivate
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.java.dataflow.TaintTracking
pragma[nomagic]
private predicate isTestPackage(Package p) {
p.getName()
.matches([
"org.junit%", "junit.%", "org.mockito%", "org.assertj%",
"com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%",
"org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%",
"org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%",
"org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions",
"org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", "org.jboss.arquillian.testng%",
"org.testng%"
])
}
/**
* A test library.
*/
private class TestLibrary extends RefType {
TestLibrary() { isTestPackage(this.getPackage()) }
}
private import semmle.code.java.dataflow.internal.ModelExclusions
private string containerAsJar(Container container) {
if container instanceof JarFile then result = container.getBaseName() else result = "rt.jar"

View File

@@ -5,6 +5,7 @@
private import java as J
private import semmle.code.java.dataflow.internal.DataFlowPrivate
private import semmle.code.java.dataflow.internal.ContainerFlow as ContainerFlow
private import semmle.code.java.dataflow.internal.ModelExclusions
private import semmle.code.java.dataflow.DataFlow as Df
private import semmle.code.java.dataflow.SSA as Ssa
private import semmle.code.java.dataflow.TaintTracking as Tt
@@ -26,34 +27,6 @@ private J::Method superImpl(J::Method m) {
not m instanceof J::ToStringMethod
}
private predicate isInTestFile(J::File file) {
file.getAbsolutePath().matches("%src/test/%") or
file.getAbsolutePath().matches("%/guava-tests/%") or
file.getAbsolutePath().matches("%/guava-testlib/%")
}
private predicate isJdkInternal(J::CompilationUnit cu) {
cu.getPackage().getName().matches("org.graalvm%") or
cu.getPackage().getName().matches("com.sun%") or
cu.getPackage().getName().matches("sun%") or
cu.getPackage().getName().matches("jdk%") or
cu.getPackage().getName().matches("java2d%") or
cu.getPackage().getName().matches("build.tools%") or
cu.getPackage().getName().matches("propertiesparser%") or
cu.getPackage().getName().matches("org.jcp%") or
cu.getPackage().getName().matches("org.w3c%") or
cu.getPackage().getName().matches("org.ietf.jgss%") or
cu.getPackage().getName().matches("org.xml.sax%") or
cu.getPackage().getName().matches("com.oracle%") or
cu.getPackage().getName().matches("org.omg%") or
cu.getPackage().getName().matches("org.relaxng%") or
cu.getPackage().getName() = "compileproperties" or
cu.getPackage().getName() = "transparentruler" or
cu.getPackage().getName() = "genstubs" or
cu.getPackage().getName() = "netscape.javascript" or
cu.getPackage().getName() = ""
}
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
cu.getPackage().getName().matches("javax.swing%") or
cu.getPackage().getName().matches("java.awt%")
@@ -63,13 +36,8 @@ private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
* Holds if it is relevant to generate models for `api`.
*/
private predicate isRelevantForModels(J::Callable api) {
not isInTestFile(api.getCompilationUnit().getFile()) and
not isJdkInternal(api.getCompilationUnit()) and
not isInfrequentlyUsed(api.getCompilationUnit()) and
not api instanceof J::MainMethod and
not api instanceof J::StaticInitializer and
not exists(J::FunctionalExpr funcExpr | api = funcExpr.asMethod()) and
not api.(J::Constructor).isParameterless()
not isUninterestingForModels(api) and
not isInfrequentlyUsed(api.getCompilationUnit())
}
/**

View File

@@ -61,37 +61,11 @@ private module DefaultValueFlow = DataFlow::Global<DefaultFlowConfig>;
private module DefaultTaintFlow = TaintTracking::Global<DefaultFlowConfig>;
class DefaultValueFlowConf extends DataFlow::Configuration {
DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" }
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
override predicate isSink(DataFlow::Node n) {
exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
}
override int fieldFlowBranchLimit() { result = 1000 }
}
class DefaultTaintFlowConf extends TaintTracking::Configuration {
DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" }
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
override predicate isSink(DataFlow::Node n) {
exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
}
override int fieldFlowBranchLimit() { result = 1000 }
}
private string getSourceArgString(DataFlow::Node src) {
defaultSource(src) and
src.asExpr().(MethodAccess).getAnArgument().(StringLiteral).getValue() = result
}
abstract class EnableLegacyConfiguration extends Unit { }
class InlineFlowTest extends InlineExpectationsTest {
InlineFlowTest() { this = "HasFlowTest" }
@@ -116,18 +90,10 @@ class InlineFlowTest extends InlineExpectationsTest {
}
predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) {
if exists(EnableLegacyConfiguration e)
then getValueFlowConfig().hasFlow(src, sink)
else DefaultValueFlow::flow(src, sink)
DefaultValueFlow::flow(src, sink)
}
predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) {
if exists(EnableLegacyConfiguration e)
then getTaintFlowConfig().hasFlow(src, sink)
else DefaultTaintFlow::flow(src, sink)
DefaultTaintFlow::flow(src, sink)
}
DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) }
DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) }
}

View File

@@ -93,7 +93,7 @@ public class Test {
sink(sj1.add((CharSequence)source())); // $hasTaintFlow
StringJoiner sj2 = (StringJoiner)source();
sink(sj2.add("test")); // $hasTaintFlow
sink(sj2.add("test")); // $hasValueFlow
}
// top 300-500 JDK APIs tests

View File

@@ -0,0 +1,92 @@
import java.util.StringJoiner;
public class StringJoinerTests {
Object taint() {
return null;
}
void sink(Object o) {}
public void test() throws Exception {
{
// "java.util;StringJoiner;false;StringJoiner;(CharSequence);;Argument[0];Argument[-1];taint;manual"
StringJoiner out = null;
CharSequence in = (CharSequence) taint();
out = new StringJoiner(in);
sink(out);
}
{
// "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[-1];taint;manual"
StringJoiner out = null;
CharSequence in = (CharSequence) taint();
out = new StringJoiner(in, null, null);
sink(out);
}
{
// "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[-1];taint;manual"
StringJoiner out = null;
CharSequence in = (CharSequence) taint();
out = new StringJoiner(null, in, null);
sink(out);
}
{
// "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[-1];taint;manual"
StringJoiner out = null;
CharSequence in = (CharSequence) taint();
out = new StringJoiner(null, null, in);
sink(out);
}
{
// "java.util;StringJoiner;false;add;;;Argument[-1];ReturnValue;value;manual"
StringJoiner out = null;
StringJoiner in = (StringJoiner) taint();
out = in.add(null);
sink(out);
}
{
// "java.util;StringJoiner;false;add;;;Argument[0];Argument[-1];taint;manual"
StringJoiner out = null;
CharSequence in = (CharSequence) taint();
out.add(in);
sink(out);
}
{
// "java.util;StringJoiner;false;merge;;;Argument[-1];ReturnValue;value;manual"
StringJoiner out = null;
StringJoiner in = (StringJoiner) taint();
out = in.merge(null);
sink(out);
}
{
// "java.util;StringJoiner;false;merge;;;Argument[0];Argument[-1];taint;manual"
StringJoiner out = null;
StringJoiner in = (StringJoiner) taint();
out.merge(in);
sink(out);
}
{
// "java.util;StringJoiner;false;setEmptyValue;;;Argument[-1];ReturnValue;taint;manual"
StringJoiner out = null;
StringJoiner in = (StringJoiner) taint();
out = in.setEmptyValue(null);
sink(out);
}
{
// "java.util;StringJoiner;false;setEmptyValue;;;Argument[0];Argument[-1];taint;manual"
StringJoiner out = null;
CharSequence in = (CharSequence) taint();
out.setEmptyValue(in);
sink(out);
}
{
// "java.util;StringJoiner;false;toString;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
StringJoiner in = (StringJoiner) taint();
out = in.toString();
sink(out);
}
}
}

View File

@@ -71,6 +71,17 @@
| StringBuilderTests.java:70:15:70:21 | taint(...) | StringBuilderTests.java:73:10:73:26 | new String(...) |
| StringBuilderTests.java:79:15:79:21 | taint(...) | StringBuilderTests.java:80:10:80:40 | toString(...) |
| StringBuilderTests.java:86:15:86:21 | taint(...) | StringBuilderTests.java:87:10:87:27 | substring(...) |
| StringJoinerTests.java:15:37:15:43 | taint(...) | StringJoinerTests.java:17:9:17:11 | out |
| StringJoinerTests.java:22:37:22:43 | taint(...) | StringJoinerTests.java:24:9:24:11 | out |
| StringJoinerTests.java:29:37:29:43 | taint(...) | StringJoinerTests.java:31:9:31:11 | out |
| StringJoinerTests.java:36:37:36:43 | taint(...) | StringJoinerTests.java:38:9:38:11 | out |
| StringJoinerTests.java:43:37:43:43 | taint(...) | StringJoinerTests.java:45:9:45:11 | out |
| StringJoinerTests.java:50:37:50:43 | taint(...) | StringJoinerTests.java:52:9:52:11 | out |
| StringJoinerTests.java:57:37:57:43 | taint(...) | StringJoinerTests.java:59:9:59:11 | out |
| StringJoinerTests.java:64:37:64:43 | taint(...) | StringJoinerTests.java:66:9:66:11 | out |
| StringJoinerTests.java:71:37:71:43 | taint(...) | StringJoinerTests.java:73:9:73:11 | out |
| StringJoinerTests.java:78:37:78:43 | taint(...) | StringJoinerTests.java:80:9:80:11 | out |
| StringJoinerTests.java:85:37:85:43 | taint(...) | StringJoinerTests.java:87:9:87:11 | out |
| Varargs.java:7:8:7:14 | taint(...) | Varargs.java:14:10:14:10 | s |
| Varargs.java:8:8:8:14 | taint(...) | Varargs.java:19:10:19:10 | s |
| Varargs.java:8:17:8:23 | taint(...) | Varargs.java:19:10:19:10 | s |

View File

@@ -3,22 +3,26 @@ import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineFlowTest
class EnableLegacy extends EnableLegacyConfiguration {
EnableLegacy() { exists(this) }
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
DefaultFlowConfig::isSource(node)
or
node instanceof RemoteFlowSource
}
predicate isSink = DefaultFlowConfig::isSink/1;
}
class TaintFlowConf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node n) {
super.isSource(n)
or
n instanceof RemoteFlowSource
}
}
module TaintFlow = TaintTracking::Global<Config>;
class ValueFlowConf extends DefaultValueFlowConf {
override predicate isSource(DataFlow::Node n) {
super.isSource(n)
or
n instanceof RemoteFlowSource
module ValueFlow = DataFlow::Global<Config>;
class Test extends InlineFlowTest {
override predicate hasTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
TaintFlow::flow(source, sink)
}
override predicate hasValueFlow(DataFlow::Node source, DataFlow::Node sink) {
ValueFlow::flow(source, sink)
}
}

View File

@@ -1,22 +1,37 @@
import java
import semmle.code.java.dataflow.TaintTracking
import TestUtilities.InlineFlowTest
import semmle.code.java.dataflow.FlowSources
class EnableLegacy extends EnableLegacyConfiguration {
EnableLegacy() { exists(this) }
}
class SliceValueFlowConf extends DefaultValueFlowConf {
override predicate isSource(DataFlow::Node source) {
super.isSource(source) or source instanceof RemoteFlowSource
module SliceValueFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
DefaultFlowConfig::isSource(source) or source instanceof RemoteFlowSource
}
predicate isSink = DefaultFlowConfig::isSink/1;
}
class SliceTaintFlowConf extends DefaultTaintFlowConf {
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
super.allowImplicitRead(node, c)
or
isSink(node) and
module SliceValueFlow = DataFlow::Global<SliceValueFlowConfig>;
module SliceTaintFlowConfig implements DataFlow::ConfigSig {
predicate isSource = DefaultFlowConfig::isSource/1;
predicate isSink = DefaultFlowConfig::isSink/1;
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
DefaultFlowConfig::isSink(node) and
c.(DataFlow::SyntheticFieldContent).getField() = "androidx.slice.Slice.action"
}
}
module SliceTaintFlow = TaintTracking::Global<SliceTaintFlowConfig>;
class SliceFlowTest extends InlineFlowTest {
override predicate hasValueFlow(DataFlow::Node source, DataFlow::Node sink) {
SliceValueFlow::flow(source, sink)
}
override predicate hasTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
SliceTaintFlow::flow(source, sink)
}
}

View File

@@ -1,15 +1,22 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineFlowTest
class Conf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node node) {
super.isSource(node)
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
DefaultFlowConfig::isSource(node)
or
node instanceof RemoteFlowSource
}
predicate isSink = DefaultFlowConfig::isSink/1;
}
class LegacyConfig extends EnableLegacyConfiguration {
LegacyConfig() { this instanceof Unit }
module Flow = TaintTracking::Global<Config>;
class Test extends InlineFlowTest {
override predicate hasTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
Flow::flow(source, sink)
}
}

View File

@@ -1,10 +1,17 @@
import java
import semmle.code.java.dataflow.DataFlow
import TestUtilities.InlineFlowTest
class EnableLegacy extends EnableLegacyConfiguration {
EnableLegacy() { exists(this) }
module OkHttpFlowConfig implements DataFlow::ConfigSig {
predicate isSource = DefaultFlowConfig::isSource/1;
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) or sinkNode(n, "open-url") }
}
class FlowConf extends DefaultValueFlowConf {
override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") }
module OkHttpFlow = DataFlow::Global<OkHttpFlowConfig>;
class OkHttpTest extends InlineFlowTest {
override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) {
OkHttpFlow::flow(src, sink)
}
}

View File

@@ -1,10 +1,15 @@
import java
import semmle.code.java.dataflow.DataFlow
import TestUtilities.InlineFlowTest
class EnableLegacy extends EnableLegacyConfiguration {
EnableLegacy() { exists(this) }
module FlowConfig implements DataFlow::ConfigSig {
predicate isSource = DefaultFlowConfig::isSource/1;
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) or sinkNode(n, "open-url") }
}
class FlowConf extends DefaultValueFlowConf {
override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") }
module Flow = DataFlow::Global<FlowConfig>;
class RetrofitFlowTest extends InlineFlowTest {
override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { Flow::flow(src, sink) }
}

View File

@@ -380,20 +380,6 @@ public class Test {
FileCopyUtils.copy(in, out);
sink(out); // $hasTaintFlow
}
{
// "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual"
File out = null;
byte[] in = (byte[])source();
FileCopyUtils.copy(in, out);
sink(out); // $hasTaintFlow
}
{
// "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual"
File out = null;
File in = (File)source();
FileCopyUtils.copy(in, out);
sink(out); // $hasTaintFlow
}
{
// "org.springframework.util;FileCopyUtils;false;copyToByteArray;;;Argument[0];ReturnValue;taint;manual"
byte[] out = null;

View File

@@ -7,8 +7,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence
{
public char charAt(int p0){ return '0'; } // manual summary
public int length(){ return 0; } // manual neutral
public void setCharAt(int p0, char p1){} // manual neutral, Note: not currently counted by query due to exclusions in `TargetApiSpecific`
public void setLength(int p0){} // manual neutral, Note: not currently counted by query due to exclusions in `TargetApiSpecific`
public void setCharAt(int p0, char p1){} // manual neutral
public void setLength(int p0){} // manual neutral
public AbstractStringBuilder append(CharSequence p0){ return null; }

View File

@@ -7,7 +7,7 @@ import java.io.Serializable;
abstract public class Enum<E extends Enum<E>> implements Comparable<E>, Serializable
{
protected Enum() {}
protected Enum(String p0, int p1){} // manual neutral, Note: this will not be counted in query results since `protected` not `public`
protected Enum(String p0, int p1){} // manual neutral
public String toString(){ return null; } // manual neutral
public final String name(){ return null; } // manual neutral
public final boolean equals(Object p0){ return false; } // manual neutral

View File

@@ -12,7 +12,4 @@ public class StringBuffer extends AbstractStringBuilder implements Serializable
public StringBuffer append(char p0){ return null; } // manual summary
public StringBuffer append(CharSequence s, int start, int end) { return null; }
public void setCharAt(int p0, char p1){}
public void setLength(int p0){}
}

View File

@@ -19,7 +19,4 @@ public class StringBuilder extends AbstractStringBuilder implements Serializable
public StringBuilder(int p0){} // manual summary
public StringBuilder append(CharSequence s, int start, int end) { return null; }
public void setCharAt(int p0, char p1){}
public void setLength(int p0){}
}

View File

@@ -1,21 +1,23 @@
| java.io | 0 | 0 | 22 | 9 | 31 | 0.7096774193548387 | 0.0 | 0.7096774193548387 | 0.0 | NaN | 0.2903225806451613 |
| java.lang | 0 | 0 | 60 | 89 | 149 | 0.40268456375838924 | 0.0 | 0.40268456375838924 | 0.0 | NaN | 0.5973154362416108 |
| java.awt | 0 | 0 | 2 | 1 | 3 | 0.6666666666666666 | 0.0 | 0.6666666666666666 | 0.0 | NaN | 0.3333333333333333 |
| java.io | 0 | 0 | 22 | 15 | 37 | 0.5945945945945946 | 0.0 | 0.5945945945945946 | 0.0 | NaN | 0.40540540540540543 |
| java.lang | 0 | 0 | 62 | 94 | 156 | 0.3974358974358974 | 0.0 | 0.3974358974358974 | 0.0 | NaN | 0.6025641025641025 |
| java.lang.invoke | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.lang.reflect | 0 | 0 | 0 | 4 | 4 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.math | 0 | 0 | 0 | 16 | 16 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.net | 0 | 0 | 5 | 0 | 5 | 1.0 | 0.0 | 1.0 | 0.0 | NaN | 0.0 |
| java.nio | 0 | 0 | 2 | 3 | 5 | 0.4 | 0.0 | 0.4 | 0.0 | NaN | 0.6 |
| java.nio.charset | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.nio.file | 0 | 0 | 1 | 1 | 2 | 0.5 | 0.0 | 0.5 | 0.0 | NaN | 0.5 |
| java.sql | 0 | 0 | 0 | 2 | 2 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.nio.file | 0 | 0 | 7 | 1 | 8 | 0.875 | 0.0 | 0.875 | 0.0 | NaN | 0.125 |
| java.sql | 0 | 0 | 2 | 14 | 16 | 0.125 | 0.0 | 0.125 | 0.0 | NaN | 0.875 |
| java.text | 0 | 0 | 0 | 5 | 5 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.time | 0 | 0 | 0 | 17 | 17 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.time.chrono | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.time.format | 0 | 0 | 0 | 2 | 2 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.util | 0 | 0 | 56 | 45 | 101 | 0.5544554455445545 | 0.0 | 0.5544554455445545 | 0.0 | NaN | 0.44554455445544555 |
| java.util.concurrent | 0 | 0 | 6 | 7 | 13 | 0.46153846153846156 | 0.0 | 0.46153846153846156 | 0.0 | NaN | 0.5384615384615384 |
| java.util | 0 | 0 | 84 | 68 | 152 | 0.5526315789473685 | 0.0 | 0.5526315789473685 | 0.0 | NaN | 0.4473684210526316 |
| java.util.concurrent | 0 | 0 | 9 | 9 | 18 | 0.5 | 0.0 | 0.5 | 0.0 | NaN | 0.5 |
| java.util.concurrent.atomic | 0 | 0 | 2 | 11 | 13 | 0.15384615384615385 | 0.0 | 0.15384615384615385 | 0.0 | NaN | 0.8461538461538461 |
| java.util.function | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.util.concurrent.locks | 0 | 0 | 0 | 2 | 2 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.util.function | 0 | 0 | 0 | 6 | 6 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
| java.util.logging | 0 | 0 | 1 | 1 | 2 | 0.5 | 0.0 | 0.5 | 0.0 | NaN | 0.5 |
| java.util.regex | 0 | 0 | 3 | 1 | 4 | 0.75 | 0.0 | 0.75 | 0.0 | NaN | 0.25 |
| java.util.stream | 0 | 0 | 4 | 5 | 9 | 0.4444444444444444 | 0.0 | 0.4444444444444444 | 0.0 | NaN | 0.5555555555555556 |
| java.util.stream | 0 | 0 | 18 | 8 | 26 | 0.6923076923076923 | 0.0 | 0.6923076923076923 | 0.0 | NaN | 0.3076923076923077 |

View File

@@ -14,108 +14,114 @@ edges
| Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) |
| Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) |
| Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:33:61:33:68 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:35:41:35:48 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:37:56:37:63 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:39:46:39:53 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:41:38:41:45 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:43:36:43:43 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:45:31:45:38 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:47:33:47:40 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:49:27:49:34 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:50:27:50:34 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:51:34:51:41 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:53:40:53:47 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:54:48:54:55 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:55:47:55:54 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:57:40:57:47 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:59:38:59:45 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:61:33:61:40 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:63:33:63:40 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:65:41:65:48 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:67:42:67:49 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:69:37:69:44 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:71:29:71:36 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:73:37:73:44 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:75:28:75:35 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:77:33:77:40 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:79:40:79:47 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:81:40:81:47 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:82:40:82:47 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:84:38:84:45 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:86:28:86:35 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:87:28:87:35 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:88:28:88:35 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:90:34:90:41 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:91:34:91:41 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:93:33:93:40 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:95:42:95:49 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:97:50:97:57 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:99:54:99:61 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:104:37:104:44 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:106:74:106:81 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:108:68:108:75 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:110:68:110:75 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:112:30:112:37 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:117:30:117:37 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:122:33:122:40 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:124:27:124:34 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:126:28:126:35 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:128:29:128:36 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:133:27:133:34 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:135:26:135:33 | source(...) : String |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:140:29:140:36 | source(...) : String |
| mad/Test.java:33:61:33:68 | source(...) : String | mad/Test.java:33:52:33:68 | (...)... |
| mad/Test.java:35:41:35:48 | source(...) : String | mad/Test.java:35:32:35:48 | (...)... |
| mad/Test.java:37:56:37:63 | source(...) : String | mad/Test.java:37:47:37:63 | (...)... |
| mad/Test.java:39:46:39:53 | source(...) : String | mad/Test.java:39:39:39:53 | (...)... |
| mad/Test.java:41:38:41:45 | source(...) : String | mad/Test.java:41:31:41:45 | (...)... |
| mad/Test.java:43:36:43:43 | source(...) : String | mad/Test.java:43:29:43:43 | (...)... |
| mad/Test.java:45:31:45:38 | source(...) : String | mad/Test.java:45:24:45:38 | (...)... |
| mad/Test.java:47:33:47:40 | source(...) : String | mad/Test.java:47:24:47:40 | (...)... |
| mad/Test.java:49:27:49:34 | source(...) : String | mad/Test.java:49:20:49:34 | (...)... |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:34:61:34:68 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:36:41:36:48 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:38:56:38:63 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:40:46:40:53 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:42:38:42:45 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:44:36:44:43 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:46:31:46:38 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:48:33:48:40 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:50:27:50:34 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:51:27:51:34 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:52:34:52:41 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:54:40:54:47 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:55:48:55:55 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:56:47:56:54 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:58:40:58:47 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:60:38:60:45 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:62:33:62:40 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:64:33:64:40 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:66:41:66:48 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:68:42:68:49 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:70:37:70:44 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:72:29:72:36 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:74:37:74:44 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:76:28:76:35 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:78:33:78:40 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:80:40:80:47 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:82:40:82:47 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:83:40:83:47 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:85:38:85:45 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:87:28:87:35 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:88:28:88:35 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:89:28:89:35 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:91:34:91:41 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:92:34:92:41 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:94:33:94:40 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:96:42:96:49 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:98:50:98:57 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:100:54:100:61 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:102:50:102:57 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:104:35:104:42 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:106:48:106:55 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:111:37:111:44 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:113:74:113:81 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:115:68:115:75 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:117:68:117:75 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:119:30:119:37 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:124:30:124:37 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:129:33:129:40 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:131:27:131:34 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:133:28:133:35 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:135:29:135:36 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:140:27:140:34 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:142:26:142:33 | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:147:29:147:36 | source(...) : String |
| mad/Test.java:34:61:34:68 | source(...) : String | mad/Test.java:34:52:34:68 | (...)... |
| mad/Test.java:36:41:36:48 | source(...) : String | mad/Test.java:36:32:36:48 | (...)... |
| mad/Test.java:38:56:38:63 | source(...) : String | mad/Test.java:38:47:38:63 | (...)... |
| mad/Test.java:40:46:40:53 | source(...) : String | mad/Test.java:40:39:40:53 | (...)... |
| mad/Test.java:42:38:42:45 | source(...) : String | mad/Test.java:42:31:42:45 | (...)... |
| mad/Test.java:44:36:44:43 | source(...) : String | mad/Test.java:44:29:44:43 | (...)... |
| mad/Test.java:46:31:46:38 | source(...) : String | mad/Test.java:46:24:46:38 | (...)... |
| mad/Test.java:48:33:48:40 | source(...) : String | mad/Test.java:48:24:48:40 | (...)... |
| mad/Test.java:50:27:50:34 | source(...) : String | mad/Test.java:50:20:50:34 | (...)... |
| mad/Test.java:51:34:51:41 | source(...) : String | mad/Test.java:51:20:51:41 | (...)... |
| mad/Test.java:53:40:53:47 | source(...) : String | mad/Test.java:53:33:53:47 | (...)... |
| mad/Test.java:54:48:54:55 | source(...) : String | mad/Test.java:54:33:54:55 | (...)... |
| mad/Test.java:55:47:55:54 | source(...) : String | mad/Test.java:55:40:55:54 | (...)... |
| mad/Test.java:57:40:57:47 | source(...) : String | mad/Test.java:57:33:57:47 | (...)... |
| mad/Test.java:59:38:59:45 | source(...) : String | mad/Test.java:59:31:59:45 | (...)... |
| mad/Test.java:61:33:61:40 | source(...) : String | mad/Test.java:61:26:61:40 | (...)... |
| mad/Test.java:63:33:63:40 | source(...) : String | mad/Test.java:63:26:63:40 | (...)... |
| mad/Test.java:65:41:65:48 | source(...) : String | mad/Test.java:65:34:65:48 | (...)... |
| mad/Test.java:67:42:67:49 | source(...) : String | mad/Test.java:67:35:67:49 | (...)... |
| mad/Test.java:69:37:69:44 | source(...) : String | mad/Test.java:69:30:69:44 | (...)... |
| mad/Test.java:71:29:71:36 | source(...) : String | mad/Test.java:71:22:71:36 | (...)... |
| mad/Test.java:73:37:73:44 | source(...) : String | mad/Test.java:73:30:73:44 | (...)... |
| mad/Test.java:75:28:75:35 | source(...) : String | mad/Test.java:75:21:75:35 | (...)... |
| mad/Test.java:77:33:77:40 | source(...) : String | mad/Test.java:77:26:77:40 | (...)... |
| mad/Test.java:79:40:79:47 | source(...) : String | mad/Test.java:79:33:79:47 | (...)... |
| mad/Test.java:81:40:81:47 | source(...) : String | mad/Test.java:81:33:81:47 | (...)... |
| mad/Test.java:51:27:51:34 | source(...) : String | mad/Test.java:51:20:51:34 | (...)... |
| mad/Test.java:52:34:52:41 | source(...) : String | mad/Test.java:52:20:52:41 | (...)... |
| mad/Test.java:54:40:54:47 | source(...) : String | mad/Test.java:54:33:54:47 | (...)... |
| mad/Test.java:55:48:55:55 | source(...) : String | mad/Test.java:55:33:55:55 | (...)... |
| mad/Test.java:56:47:56:54 | source(...) : String | mad/Test.java:56:40:56:54 | (...)... |
| mad/Test.java:58:40:58:47 | source(...) : String | mad/Test.java:58:33:58:47 | (...)... |
| mad/Test.java:60:38:60:45 | source(...) : String | mad/Test.java:60:31:60:45 | (...)... |
| mad/Test.java:62:33:62:40 | source(...) : String | mad/Test.java:62:26:62:40 | (...)... |
| mad/Test.java:64:33:64:40 | source(...) : String | mad/Test.java:64:26:64:40 | (...)... |
| mad/Test.java:66:41:66:48 | source(...) : String | mad/Test.java:66:34:66:48 | (...)... |
| mad/Test.java:68:42:68:49 | source(...) : String | mad/Test.java:68:35:68:49 | (...)... |
| mad/Test.java:70:37:70:44 | source(...) : String | mad/Test.java:70:30:70:44 | (...)... |
| mad/Test.java:72:29:72:36 | source(...) : String | mad/Test.java:72:22:72:36 | (...)... |
| mad/Test.java:74:37:74:44 | source(...) : String | mad/Test.java:74:30:74:44 | (...)... |
| mad/Test.java:76:28:76:35 | source(...) : String | mad/Test.java:76:21:76:35 | (...)... |
| mad/Test.java:78:33:78:40 | source(...) : String | mad/Test.java:78:26:78:40 | (...)... |
| mad/Test.java:80:40:80:47 | source(...) : String | mad/Test.java:80:33:80:47 | (...)... |
| mad/Test.java:82:40:82:47 | source(...) : String | mad/Test.java:82:33:82:47 | (...)... |
| mad/Test.java:84:38:84:45 | source(...) : String | mad/Test.java:84:31:84:45 | (...)... |
| mad/Test.java:86:28:86:35 | source(...) : String | mad/Test.java:86:21:86:35 | (...)... |
| mad/Test.java:83:40:83:47 | source(...) : String | mad/Test.java:83:33:83:47 | (...)... |
| mad/Test.java:85:38:85:45 | source(...) : String | mad/Test.java:85:31:85:45 | (...)... |
| mad/Test.java:87:28:87:35 | source(...) : String | mad/Test.java:87:21:87:35 | (...)... |
| mad/Test.java:88:28:88:35 | source(...) : String | mad/Test.java:88:21:88:35 | (...)... |
| mad/Test.java:90:34:90:41 | source(...) : String | mad/Test.java:90:27:90:41 | (...)... |
| mad/Test.java:89:28:89:35 | source(...) : String | mad/Test.java:89:21:89:35 | (...)... |
| mad/Test.java:91:34:91:41 | source(...) : String | mad/Test.java:91:27:91:41 | (...)... |
| mad/Test.java:93:33:93:40 | source(...) : String | mad/Test.java:93:26:93:40 | (...)... |
| mad/Test.java:95:42:95:49 | source(...) : String | mad/Test.java:95:35:95:49 | (...)... |
| mad/Test.java:97:50:97:57 | source(...) : String | mad/Test.java:97:41:97:57 | (...)... |
| mad/Test.java:99:54:99:61 | source(...) : String | mad/Test.java:99:45:99:61 | (...)... |
| mad/Test.java:104:37:104:44 | source(...) : String | mad/Test.java:104:30:104:44 | (...)... |
| mad/Test.java:106:74:106:81 | source(...) : String | mad/Test.java:106:40:106:81 | (...)... |
| mad/Test.java:108:68:108:75 | source(...) : String | mad/Test.java:108:34:108:75 | (...)... |
| mad/Test.java:110:68:110:75 | source(...) : String | mad/Test.java:110:34:110:75 | (...)... |
| mad/Test.java:112:30:112:37 | source(...) : String | mad/Test.java:112:23:112:37 | (...)... |
| mad/Test.java:117:30:117:37 | source(...) : String | mad/Test.java:117:23:117:37 | (...)... |
| mad/Test.java:122:33:122:40 | source(...) : String | mad/Test.java:122:23:122:40 | (...)... |
| mad/Test.java:124:27:124:34 | source(...) : String | mad/Test.java:124:20:124:34 | (...)... |
| mad/Test.java:126:28:126:35 | source(...) : String | mad/Test.java:126:21:126:35 | (...)... |
| mad/Test.java:128:29:128:36 | source(...) : String | mad/Test.java:128:22:128:36 | (...)... |
| mad/Test.java:133:27:133:34 | source(...) : String | mad/Test.java:133:20:133:34 | (...)... |
| mad/Test.java:135:26:135:33 | source(...) : String | mad/Test.java:135:19:135:33 | (...)... |
| mad/Test.java:140:29:140:36 | source(...) : String | mad/Test.java:140:20:140:36 | (...)... |
| mad/Test.java:92:34:92:41 | source(...) : String | mad/Test.java:92:27:92:41 | (...)... |
| mad/Test.java:94:33:94:40 | source(...) : String | mad/Test.java:94:26:94:40 | (...)... |
| mad/Test.java:96:42:96:49 | source(...) : String | mad/Test.java:96:35:96:49 | (...)... |
| mad/Test.java:98:50:98:57 | source(...) : String | mad/Test.java:98:41:98:57 | (...)... |
| mad/Test.java:100:54:100:61 | source(...) : String | mad/Test.java:100:45:100:61 | (...)... |
| mad/Test.java:102:50:102:57 | source(...) : String | mad/Test.java:102:43:102:57 | (...)... |
| mad/Test.java:104:35:104:42 | source(...) : String | mad/Test.java:104:28:104:42 | (...)... |
| mad/Test.java:106:48:106:55 | source(...) : String | mad/Test.java:106:41:106:55 | (...)... |
| mad/Test.java:111:37:111:44 | source(...) : String | mad/Test.java:111:30:111:44 | (...)... |
| mad/Test.java:113:74:113:81 | source(...) : String | mad/Test.java:113:40:113:81 | (...)... |
| mad/Test.java:115:68:115:75 | source(...) : String | mad/Test.java:115:34:115:75 | (...)... |
| mad/Test.java:117:68:117:75 | source(...) : String | mad/Test.java:117:34:117:75 | (...)... |
| mad/Test.java:119:30:119:37 | source(...) : String | mad/Test.java:119:23:119:37 | (...)... |
| mad/Test.java:124:30:124:37 | source(...) : String | mad/Test.java:124:23:124:37 | (...)... |
| mad/Test.java:129:33:129:40 | source(...) : String | mad/Test.java:129:23:129:40 | (...)... |
| mad/Test.java:131:27:131:34 | source(...) : String | mad/Test.java:131:20:131:34 | (...)... |
| mad/Test.java:133:28:133:35 | source(...) : String | mad/Test.java:133:21:133:35 | (...)... |
| mad/Test.java:135:29:135:36 | source(...) : String | mad/Test.java:135:22:135:36 | (...)... |
| mad/Test.java:140:27:140:34 | source(...) : String | mad/Test.java:140:20:140:34 | (...)... |
| mad/Test.java:142:26:142:33 | source(...) : String | mad/Test.java:142:19:142:33 | (...)... |
| mad/Test.java:147:29:147:36 | source(...) : String | mad/Test.java:147:20:147:36 | (...)... |
nodes
| Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| Test.java:24:20:24:23 | temp | semmle.label | temp |
@@ -136,109 +142,115 @@ nodes
| Test.java:99:12:99:33 | new URI(...) | semmle.label | new URI(...) |
| Test.java:100:12:100:45 | new URI(...) | semmle.label | new URI(...) |
| Test.java:101:12:101:54 | new URI(...) | semmle.label | new URI(...) |
| mad/Test.java:28:16:28:36 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| mad/Test.java:33:52:33:68 | (...)... | semmle.label | (...)... |
| mad/Test.java:33:61:33:68 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:35:32:35:48 | (...)... | semmle.label | (...)... |
| mad/Test.java:35:41:35:48 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:37:47:37:63 | (...)... | semmle.label | (...)... |
| mad/Test.java:37:56:37:63 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:39:39:39:53 | (...)... | semmle.label | (...)... |
| mad/Test.java:39:46:39:53 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:41:31:41:45 | (...)... | semmle.label | (...)... |
| mad/Test.java:41:38:41:45 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:43:29:43:43 | (...)... | semmle.label | (...)... |
| mad/Test.java:43:36:43:43 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:45:24:45:38 | (...)... | semmle.label | (...)... |
| mad/Test.java:45:31:45:38 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:47:24:47:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:47:33:47:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:49:20:49:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:49:27:49:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:29:16:29:36 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| mad/Test.java:34:52:34:68 | (...)... | semmle.label | (...)... |
| mad/Test.java:34:61:34:68 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:36:32:36:48 | (...)... | semmle.label | (...)... |
| mad/Test.java:36:41:36:48 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:38:47:38:63 | (...)... | semmle.label | (...)... |
| mad/Test.java:38:56:38:63 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:40:39:40:53 | (...)... | semmle.label | (...)... |
| mad/Test.java:40:46:40:53 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:42:31:42:45 | (...)... | semmle.label | (...)... |
| mad/Test.java:42:38:42:45 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:44:29:44:43 | (...)... | semmle.label | (...)... |
| mad/Test.java:44:36:44:43 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:46:24:46:38 | (...)... | semmle.label | (...)... |
| mad/Test.java:46:31:46:38 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:48:24:48:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:48:33:48:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:50:20:50:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:50:27:50:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:51:20:51:41 | (...)... | semmle.label | (...)... |
| mad/Test.java:51:34:51:41 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:53:33:53:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:53:40:53:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:54:33:54:55 | (...)... | semmle.label | (...)... |
| mad/Test.java:54:48:54:55 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:55:40:55:54 | (...)... | semmle.label | (...)... |
| mad/Test.java:55:47:55:54 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:57:33:57:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:57:40:57:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:59:31:59:45 | (...)... | semmle.label | (...)... |
| mad/Test.java:59:38:59:45 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:61:26:61:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:61:33:61:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:63:26:63:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:63:33:63:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:65:34:65:48 | (...)... | semmle.label | (...)... |
| mad/Test.java:65:41:65:48 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:67:35:67:49 | (...)... | semmle.label | (...)... |
| mad/Test.java:67:42:67:49 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:69:30:69:44 | (...)... | semmle.label | (...)... |
| mad/Test.java:69:37:69:44 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:71:22:71:36 | (...)... | semmle.label | (...)... |
| mad/Test.java:71:29:71:36 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:73:30:73:44 | (...)... | semmle.label | (...)... |
| mad/Test.java:73:37:73:44 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:75:21:75:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:75:28:75:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:77:26:77:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:77:33:77:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:79:33:79:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:79:40:79:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:81:33:81:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:81:40:81:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:51:20:51:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:51:27:51:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:52:20:52:41 | (...)... | semmle.label | (...)... |
| mad/Test.java:52:34:52:41 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:54:33:54:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:54:40:54:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:55:33:55:55 | (...)... | semmle.label | (...)... |
| mad/Test.java:55:48:55:55 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:56:40:56:54 | (...)... | semmle.label | (...)... |
| mad/Test.java:56:47:56:54 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:58:33:58:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:58:40:58:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:60:31:60:45 | (...)... | semmle.label | (...)... |
| mad/Test.java:60:38:60:45 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:62:26:62:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:62:33:62:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:64:26:64:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:64:33:64:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:66:34:66:48 | (...)... | semmle.label | (...)... |
| mad/Test.java:66:41:66:48 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:68:35:68:49 | (...)... | semmle.label | (...)... |
| mad/Test.java:68:42:68:49 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:70:30:70:44 | (...)... | semmle.label | (...)... |
| mad/Test.java:70:37:70:44 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:72:22:72:36 | (...)... | semmle.label | (...)... |
| mad/Test.java:72:29:72:36 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:74:30:74:44 | (...)... | semmle.label | (...)... |
| mad/Test.java:74:37:74:44 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:76:21:76:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:76:28:76:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:78:26:78:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:78:33:78:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:80:33:80:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:80:40:80:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:82:33:82:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:82:40:82:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:84:31:84:45 | (...)... | semmle.label | (...)... |
| mad/Test.java:84:38:84:45 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:86:21:86:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:86:28:86:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:83:33:83:47 | (...)... | semmle.label | (...)... |
| mad/Test.java:83:40:83:47 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:85:31:85:45 | (...)... | semmle.label | (...)... |
| mad/Test.java:85:38:85:45 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:87:21:87:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:87:28:87:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:88:21:88:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:88:28:88:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:90:27:90:41 | (...)... | semmle.label | (...)... |
| mad/Test.java:90:34:90:41 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:89:21:89:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:89:28:89:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:91:27:91:41 | (...)... | semmle.label | (...)... |
| mad/Test.java:91:34:91:41 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:93:26:93:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:93:33:93:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:95:35:95:49 | (...)... | semmle.label | (...)... |
| mad/Test.java:95:42:95:49 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:97:41:97:57 | (...)... | semmle.label | (...)... |
| mad/Test.java:97:50:97:57 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:99:45:99:61 | (...)... | semmle.label | (...)... |
| mad/Test.java:99:54:99:61 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:104:30:104:44 | (...)... | semmle.label | (...)... |
| mad/Test.java:104:37:104:44 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:106:40:106:81 | (...)... | semmle.label | (...)... |
| mad/Test.java:106:74:106:81 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:108:34:108:75 | (...)... | semmle.label | (...)... |
| mad/Test.java:108:68:108:75 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:110:34:110:75 | (...)... | semmle.label | (...)... |
| mad/Test.java:110:68:110:75 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:112:23:112:37 | (...)... | semmle.label | (...)... |
| mad/Test.java:112:30:112:37 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:117:23:117:37 | (...)... | semmle.label | (...)... |
| mad/Test.java:117:30:117:37 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:122:23:122:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:122:33:122:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:124:20:124:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:124:27:124:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:126:21:126:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:126:28:126:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:128:22:128:36 | (...)... | semmle.label | (...)... |
| mad/Test.java:128:29:128:36 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:133:20:133:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:133:27:133:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:135:19:135:33 | (...)... | semmle.label | (...)... |
| mad/Test.java:135:26:135:33 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:140:20:140:36 | (...)... | semmle.label | (...)... |
| mad/Test.java:140:29:140:36 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:92:27:92:41 | (...)... | semmle.label | (...)... |
| mad/Test.java:92:34:92:41 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:94:26:94:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:94:33:94:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:96:35:96:49 | (...)... | semmle.label | (...)... |
| mad/Test.java:96:42:96:49 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:98:41:98:57 | (...)... | semmle.label | (...)... |
| mad/Test.java:98:50:98:57 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:100:45:100:61 | (...)... | semmle.label | (...)... |
| mad/Test.java:100:54:100:61 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:102:43:102:57 | (...)... | semmle.label | (...)... |
| mad/Test.java:102:50:102:57 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:104:28:104:42 | (...)... | semmle.label | (...)... |
| mad/Test.java:104:35:104:42 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:106:41:106:55 | (...)... | semmle.label | (...)... |
| mad/Test.java:106:48:106:55 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:111:30:111:44 | (...)... | semmle.label | (...)... |
| mad/Test.java:111:37:111:44 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:113:40:113:81 | (...)... | semmle.label | (...)... |
| mad/Test.java:113:74:113:81 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:115:34:115:75 | (...)... | semmle.label | (...)... |
| mad/Test.java:115:68:115:75 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:117:34:117:75 | (...)... | semmle.label | (...)... |
| mad/Test.java:117:68:117:75 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:119:23:119:37 | (...)... | semmle.label | (...)... |
| mad/Test.java:119:30:119:37 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:124:23:124:37 | (...)... | semmle.label | (...)... |
| mad/Test.java:124:30:124:37 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:129:23:129:40 | (...)... | semmle.label | (...)... |
| mad/Test.java:129:33:129:40 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:131:20:131:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:131:27:131:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:133:21:133:35 | (...)... | semmle.label | (...)... |
| mad/Test.java:133:28:133:35 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:135:22:135:36 | (...)... | semmle.label | (...)... |
| mad/Test.java:135:29:135:36 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:140:20:140:34 | (...)... | semmle.label | (...)... |
| mad/Test.java:140:27:140:34 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:142:19:142:33 | (...)... | semmle.label | (...)... |
| mad/Test.java:142:26:142:33 | source(...) : String | semmle.label | source(...) : String |
| mad/Test.java:147:20:147:36 | (...)... | semmle.label | (...)... |
| mad/Test.java:147:29:147:36 | source(...) : String | semmle.label | source(...) : String |
subpaths
#select
| Test.java:24:11:24:24 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
@@ -252,54 +264,57 @@ subpaths
| Test.java:99:3:99:34 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
| Test.java:100:3:100:46 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
| Test.java:101:3:101:55 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
| mad/Test.java:33:52:33:68 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:33:52:33:68 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:35:32:35:48 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:35:32:35:48 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:37:47:37:63 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:37:47:37:63 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:39:39:39:53 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:39:39:39:53 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:41:31:41:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:41:31:41:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:43:29:43:43 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:43:29:43:43 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:45:24:45:38 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:45:24:45:38 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:47:9:47:41 | new FileReader(...) | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:47:24:47:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:49:20:49:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:49:20:49:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:50:20:50:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:50:20:50:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:51:20:51:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:51:20:51:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:53:33:53:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:53:33:53:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:54:33:54:55 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:54:33:54:55 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:55:40:55:54 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:55:40:55:54 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:57:33:57:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:57:33:57:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:59:31:59:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:59:31:59:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:61:26:61:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:61:26:61:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:63:26:63:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:63:26:63:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:65:34:65:48 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:65:34:65:48 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:67:35:67:49 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:67:35:67:49 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:69:30:69:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:69:30:69:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:71:22:71:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:71:22:71:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:73:30:73:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:73:30:73:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:75:21:75:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:75:21:75:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:77:26:77:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:77:26:77:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:79:33:79:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:79:33:79:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:81:33:81:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:81:33:81:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:82:33:82:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:82:33:82:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:84:31:84:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:84:31:84:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:86:21:86:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:86:21:86:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:87:21:87:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:87:21:87:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:88:21:88:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:88:21:88:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:90:27:90:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:90:27:90:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:91:27:91:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:91:27:91:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:93:26:93:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:93:26:93:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:95:35:95:49 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:95:35:95:49 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:97:41:97:57 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:97:41:97:57 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:99:45:99:61 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:99:45:99:61 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:104:30:104:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:104:30:104:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:106:40:106:81 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:106:40:106:81 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:108:34:108:75 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:108:34:108:75 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:110:34:110:75 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:110:34:110:75 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:112:23:112:37 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:112:23:112:37 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:117:23:117:37 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:117:23:117:37 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:122:23:122:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:122:23:122:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:124:20:124:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:124:20:124:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:126:21:126:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:126:21:126:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:128:22:128:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:128:22:128:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:133:20:133:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:133:20:133:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:135:19:135:33 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:135:19:135:33 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:140:20:140:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:140:20:140:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
| mad/Test.java:34:52:34:68 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:34:52:34:68 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:36:32:36:48 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:36:32:36:48 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:38:47:38:63 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:38:47:38:63 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:40:39:40:53 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:40:39:40:53 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:42:31:42:45 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:42:31:42:45 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:44:29:44:43 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:44:29:44:43 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:46:24:46:38 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:46:24:46:38 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:48:9:48:41 | new FileReader(...) | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:48:24:48:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:50:20:50:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:50:20:50:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:51:20:51:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:51:20:51:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:52:20:52:41 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:52:20:52:41 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:54:33:54:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:54:33:54:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:55:33:55:55 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:55:33:55:55 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:56:40:56:54 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:56:40:56:54 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:58:33:58:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:58:33:58:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:60:31:60:45 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:60:31:60:45 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:62:26:62:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:62:26:62:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:64:26:64:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:64:26:64:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:66:34:66:48 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:66:34:66:48 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:68:35:68:49 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:68:35:68:49 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:70:30:70:44 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:70:30:70:44 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:72:22:72:36 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:72:22:72:36 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:74:30:74:44 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:74:30:74:44 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:76:21:76:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:76:21:76:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:78:26:78:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:78:26:78:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:80:33:80:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:80:33:80:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:82:33:82:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:82:33:82:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:83:33:83:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:83:33:83:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:85:31:85:45 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:85:31:85:45 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:87:21:87:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:87:21:87:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:88:21:88:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:88:21:88:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:89:21:89:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:89:21:89:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:91:27:91:41 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:91:27:91:41 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:92:27:92:41 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:92:27:92:41 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:94:26:94:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:94:26:94:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:96:35:96:49 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:96:35:96:49 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:98:41:98:57 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:98:41:98:57 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:100:45:100:61 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:100:45:100:61 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:102:43:102:57 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:102:43:102:57 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:104:28:104:42 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:104:28:104:42 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:106:41:106:55 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:106:41:106:55 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:111:30:111:44 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:111:30:111:44 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:113:40:113:81 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:113:40:113:81 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:115:34:115:75 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:115:34:115:75 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:117:34:117:75 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:117:34:117:75 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:119:23:119:37 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:119:23:119:37 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:124:23:124:37 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:124:23:124:37 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:129:23:129:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:129:23:129:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:131:20:131:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:131:20:131:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:133:21:133:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:133:21:133:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:135:22:135:36 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:135:22:135:36 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:140:20:140:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:140:20:140:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:142:19:142:33 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:142:19:142:33 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
| mad/Test.java:147:20:147:36 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:147:20:147:36 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |

View File

@@ -19,6 +19,7 @@ import org.apache.tools.ant.types.FileSet;
import org.codehaus.cargo.container.installer.ZipURLInstaller;
import org.kohsuke.stapler.framework.io.LargeText;
import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
import org.springframework.util.FileCopyUtils;
public class Test {
@@ -97,6 +98,12 @@ public class Test {
new ZipURLInstaller((URL) null, (String) source(), "");
// "org.codehaus.cargo.container.installer;ZipURLInstaller;true;ZipURLInstaller;(URL,String,String);;Argument[2];create-file;ai-generated"
new ZipURLInstaller((URL) null, "", (String) source());
// "org.springframework.util;FileCopyUtils;false;copy;(byte[],File);;Argument[1];create-file;manual"
FileCopyUtils.copy((byte[]) null, (File) source());
// "org.springframework.util;FileCopyUtils;false;copy;(File,File);;Argument[0];create-file;manual"
FileCopyUtils.copy((File) source(), null);
// "org.springframework.util;FileCopyUtils;false;copy;(File,File);;Argument[1];create-file;manual"
FileCopyUtils.copy((File) null, (File) source());
}
void test(AntClassLoader acl) {

View File

@@ -1 +1 @@
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6:${testdir}/../../../../../stubs/springframework-5.3.8

View File

@@ -43,6 +43,9 @@ function isTypeAlwaysSafeToExpand(type: ts.Type): boolean {
return false;
}
}
if (type.aliasSymbol != null) {
return false;
}
return true;
}
@@ -447,7 +450,7 @@ export class TypeTable {
this.isInShallowTypeContext ? TypeExtractionState.PendingShallow : TypeExtractionState.PendingFull);
// If the type is the self-type for a named type (not a generic instantiation of it),
// emit the self-type binding for that type.
if (content.startsWith("reference;") && !(isTypeReference(type) && type.target !== type)) {
if (content.startsWith("reference;") && isTypeSelfReference(type)) {
this.selfTypes.symbols.push(this.getSymbolId(type.aliasSymbol || type.symbol));
this.selfTypes.selfTypes.push(id);
}
@@ -533,7 +536,7 @@ export class TypeTable {
let enclosingType = getEnclosingTypeOfThisType(type);
if (enclosingType != null) {
return "this;" + this.getId(enclosingType, false);
} else if (symbol.parent == null) {
} else if (symbol.parent == null || isFunctionTypeOrTypeAlias(symbol.declarations?.[0])) {
// The type variable is bound on a call signature. Only extract it by name.
return "lextypevar;" + symbol.name;
} else {
@@ -614,14 +617,14 @@ export class TypeTable {
// cannot be written using TypeScript syntax - so we ignore them entirely.
return null;
}
return this.makeTypeStringVector("union", unionType.types);
return this.makeDeduplicatedTypeStringVector("union", unionType.types);
}
if (flags & ts.TypeFlags.Intersection) {
let intersectionType = type as ts.IntersectionType;
if (intersectionType.types.length === 0) {
return null; // Ignore malformed type.
}
return this.makeTypeStringVector("intersection", intersectionType.types);
return this.makeDeduplicatedTypeStringVector("intersection", intersectionType.types);
}
if (isTypeReference(type) && (type.target.objectFlags & ts.ObjectFlags.Tuple)) {
// Encode the minimum length and presence of rest element in the first two parts of the type string.
@@ -784,6 +787,27 @@ export class TypeTable {
return hash;
}
/**
* Returns the given string with the IDs of the given types appended,
* ignoring duplicates, and each separated by `;`.
*/
private makeDeduplicatedTypeStringVector(tag: string, types: ReadonlyArray<ts.Type>, length = types.length): string | null {
let seenIds = new Set<number>();
let numberOfSeenIds = 0;
let hash = tag;
for (let i = 0; i < length; ++i) {
let id = this.getId(types[i], false);
if (id == null) return null;
seenIds.add(id);
if (seenIds.size > numberOfSeenIds) {
// This ID was not seen before
++numberOfSeenIds;
hash += ";" + id;
}
}
return hash;
}
/** Returns the type of `symbol` or `null` if it could not be computed. */
private tryGetTypeOfSymbol(symbol: ts.Symbol) {
try {
@@ -1328,3 +1352,35 @@ export class TypeTable {
}
}
}
function isFunctionTypeOrTypeAlias(declaration: ts.Declaration | undefined) {
if (declaration == null) return false;
return declaration.kind === ts.SyntaxKind.FunctionType || declaration.kind === ts.SyntaxKind.TypeAliasDeclaration;
}
/**
* Given a `type` whose type-string is known to be a `reference`, returns true if this is the self-type for the referenced type.
*
* For example, for `type Foo<R> = ...` this returns true if `type` is `Foo<R>`.
*/
function isTypeSelfReference(type: ts.Type) {
if (type.aliasSymbol != null) {
const { aliasTypeArguments } = type;
if (aliasTypeArguments == null) return true;
let declaration = type.aliasSymbol.declarations?.[0];
if (declaration == null || declaration.kind !== ts.SyntaxKind.TypeAliasDeclaration) return false;
let alias = declaration as ts.TypeAliasDeclaration;
for (let i = 0; i < aliasTypeArguments.length; ++i) {
if (aliasTypeArguments[i].symbol?.declarations?.[0] !== alias.typeParameters[i]) {
return false;
}
}
return true;
} else if (isTypeReference(type)) {
return type.target === type;
} else {
// Return true because we know we have mapped this type to kind `reference`, and in the cases
// not covered above (i.e. generic types) it is always a self-reference.
return true;
}
}

View File

@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -1237,19 +1238,29 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set<Path>
List<ParseError> errors = loc == null ? Collections.emptyList() : loc.getParseErrors();
for (ParseError err : errors) {
String msg = "A parse error occurred: " + StringUtil.quoteWithBackticks(err.getMessage().trim())
+ ". Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis.";
// file, relative to the source root
DiagnosticLocation.Builder builder = DiagnosticLocation.builder();
+ ".";
Optional<DiagnosticLocation> diagLoc = Optional.empty();
if (file.startsWith(LGTM_SRC)) {
builder = builder.setFile(file.subpath(LGTM_SRC.getNameCount(), file.getNameCount()).toString());
}
DiagnosticLocation diagLoc = builder
diagLoc = DiagnosticLocation.builder()
.setFile(file.subpath(LGTM_SRC.getNameCount(), file.getNameCount()).toString()) // file, relative to the source root
.setStartLine(err.getPosition().getLine())
.setStartColumn(err.getPosition().getColumn() + 1) // convert from 0-based to 1-based
.setEndLine(err.getPosition().getLine())
.setEndColumn(err.getPosition().getColumn() + 1) // convert from 0-based to 1-based
.build();
writeDiagnostics(msg, JSDiagnosticKind.PARSE_ERROR, diagLoc);
.build()
.getOk();
}
if (diagLoc.isPresent()) {
msg += " Check the syntax of the file. If the file is invalid, correct the error or "
+ "[exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-"
+ "your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis.";
writeDiagnostics(msg, JSDiagnosticKind.PARSE_ERROR, diagLoc.get());
} else {
msg += " The affected file is not located within the code being analyzed."
+ (Env.systemEnv().isActions() ? " Please see the workflow run logs for more information." : "");
writeDiagnostics(msg, JSDiagnosticKind.PARSE_ERROR);
}
}
logEndProcess(start, "Done extracting " + file);
} catch (OutOfMemoryError oom) {

View File

@@ -0,0 +1,5 @@
---
category: fix
---
* Fixes an issue that would cause TypeScript extraction to hang in rare cases when extracting
code containing recursive generic type aliases.

View File

@@ -0,0 +1,15 @@
typeAliases
| tst.ts:1:8:1:41 | type Fo ... R \| A>; |
| tst.ts:3:8:3:42 | type Ba ... R, A]>; |
| tst.ts:5:8:5:47 | type Ba ... => A>; |
typeAliasType
| tst.ts:1:8:1:41 | type Fo ... R \| A>; | Foo<R> |
| tst.ts:3:8:3:42 | type Ba ... R, A]>; | Bar<R> |
| tst.ts:5:8:5:47 | type Ba ... => A>; | Baz<R> |
getAliasedType
| Bar<R> | <A>() => Bar<[R, A]> |
| Bar<[R, A]> | <A>() => Bar<[[R, A], A]> |
| Baz<(x: R) => A> | <A>() => Baz<(x: (x: R) => A) => A> |
| Baz<R> | <A>() => Baz<(x: R) => A> |
| Foo<R \| A> | <A>() => Foo<R \| A> |
| Foo<R> | <A>() => Foo<R \| A> |

View File

@@ -0,0 +1,8 @@
import javascript
// The extractor would hang on this test case, it doesn't matter too much what the output of the test is.
query TypeAliasDeclaration typeAliases() { any() }
query Type typeAliasType(TypeAliasDeclaration decl) { result = decl.getTypeName().getType() }
query Type getAliasedType(TypeAliasReference ref) { result = ref.getAliasedType() }

View File

@@ -0,0 +1,3 @@
{
"include": ["."]
}

View File

@@ -0,0 +1,5 @@
export type Foo<R> = <A>() => Foo<R | A>;
export type Bar<R> = <A>() => Bar<[R, A]>;
export type Baz<R> = <A>() => Baz<(x: R) => A>;

View File

@@ -43,3 +43,13 @@ def codeql_workspace(repository_name = "codeql"):
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz",
],
)
maybe(
repo_rule = http_archive,
name = "absl",
sha256 = "cec2e5bf780532bd0ac672eb8d43c0f8bbe84ca5df8718320184034b7f59a398",
urls = [
"https://github.com/abseil/abseil-cpp/archive/d2c5297a3c3948de765100cb7e5cccca1210d23c.tar.gz",
],
strip_prefix = "abseil-cpp-d2c5297a3c3948de765100cb7e5cccca1210d23c",
)

View File

@@ -1,222 +0,0 @@
#!/bin/env python3
"""
usage: test_upgrade.py [-h] [--learn] [--accept] [--verbose] [DIR ...]
Run upgrade/downgrade scripts unit tests
positional arguments:
DIR directories to look for upgrade/downgrade scripts in
options:
-h, --help show this help message and exit
--learn write down test results in expected files
--accept accept actual results
--verbose, -v print codeql output
Tests must be contained within a `test` directory directly within the upgrade/downgrade script directory, and
take the form of a `<name>.trap` file containing the initial data of the DB and `<name>.expected` containing a
form of difference between the database before and after the upgrade/downgrade is applied, similar to the format
of `codeql database diff`. It is required and checked that the initial data is consistent with `old.dbscheme`, and
it is then checked that final data is consistent with the new dbscheme.
Behavior is similar to `codeql test run`: if the test fails, a `<name>.actual` file is created, and `--accept`
can be later used to accept the test result. `--learn` can be used to directly write the result in the
`<name>.expected` file.
"""
import argparse
import pathlib
import subprocess
import sys
import typing
import shutil
import difflib
class Error(Exception):
def __str__(self):
return f">>> {super().__str__()}"
verbose = False
def codeql(*args, quiet=False, **kwargs) -> str:
cmd = ["codeql"]
cmd.extend(args)
for k, v in kwargs.items():
k = k.replace('_', '-')
cmd.append(f"--{k}" if v is True else f"--{k}={v}")
result = subprocess.run(cmd, capture_output=True, text=True)
if not quiet and verbose:
sys.stderr.write(result.stderr)
if result.returncode:
cmd = " ".join(str(arg) for arg in cmd)
out = (result.stderr + result.stdout).strip()
raise Error(f"FAILURE running {cmd}:\n{out}")
return result.stdout
def options() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Run upgrade/downgrade scripts unit tests")
parser.add_argument("--learn", action="store_true", help="write down test results in expected files")
parser.add_argument("--accept", action="store_true", help="accept actual results")
parser.add_argument("--verbose", "-v", action="store_true", help="print codeql output")
parser.add_argument("script_dirs", nargs="*", type=pathlib.Path, default=[pathlib.Path()],
metavar="DIR", help="directories to look for upgrade/downgrade scripts in")
return parser.parse_args()
def collect_tests(dirs: typing.Iterable[pathlib.Path]) -> typing.Iterable[typing.Tuple[pathlib.Path, str]]:
for dir in dirs:
for script in dir.rglob("upgrade.properties"):
if not (script.parent / "test").is_dir():
continue
script_kind = script.parents[1].name
if script_kind == "upgrades":
pack = script.parents[4]
elif script_kind == "downgrades":
pack = script.parents[2]
else:
raise Error(f"{script} is not within a standard upgrades or downgrades directory")
if pack.name == "extractor-pack":
# do not run tests within extractor packs!
continue
for test in script.parent.glob("test/*.trap"):
yield test, pack.name
def extract_tuples(db: pathlib.Path, lang: str, dbschemename: str):
"""
Slightly hacky workaround to get all tuples of a DB in the format of `database diff --no-resolve-tuples`, by
running the diff against an empty DB with the same dbscheme and parsing the result.
"""
empty = db.with_suffix(".empty")
shutil.rmtree(empty, ignore_errors=True)
codeql("database", "init", empty, source_root=".", language=lang)
(empty / "src").mkdir()
codeql("database", "finalize", empty, dbscheme=db / f"db-{lang}" / dbschemename)
diff_lines = codeql("database", "diff", empty, db, no_resolve_tuples=True, mode="tables", quiet=True).splitlines(keepends=True)
shutil.rmtree(empty)
tables = {}
for line in diff_lines:
if line.startswith("+++"):
table = pathlib.Path(line[4:].strip()).name
elif line.startswith("+"):
tables.setdefault(table, []).append(line[1:])
return tables
def run_test(test: pathlib.Path, lang: str, learn: bool):
print(">>>", test, end=" " if not verbose else "\n")
sys.stdout.flush()
upgrade_scrip_dir = test.parents[1]
dbschemename = next(f for f in upgrade_scrip_dir.glob("*.dbscheme") if f.stem != "old").name
working_dir = test.with_suffix(".testproj")
working_dir.mkdir(exist_ok=True)
shutil.copy(upgrade_scrip_dir / "old.dbscheme", working_dir / dbschemename)
# create old version of database
olddb = working_dir / "old-db"
olddataset = olddb / f"db-{lang}"
shutil.rmtree(olddb, ignore_errors=True)
codeql("database", "init", olddb, source_root=".", language=lang)
(olddb / "src").mkdir() # make sure codeql does not complain about non extracted sources
(olddb / "trap" / lang).mkdir(parents=True)
shutil.copy(test, olddb / "trap" / lang)
codeql("database", "finalize", olddb, dbscheme=working_dir / dbschemename)
with open(olddataset / f"{dbschemename}.stats", "w") as stats:
print("<dbstats><typesizes /><stats /></dbstats>", file=stats)
codeql("dataset", "check", olddataset)
# perform upgrade
newdb = working_dir / "new-db"
newdataset = newdb / f"db-{lang}"
shutil.rmtree(newdb, ignore_errors=True)
shutil.copytree(olddb, newdb)
codeql("execute", "upgrades", newdataset, upgrade_scrip_dir)
# sometimes the above generates a stats file in the script dir, let's clean it up
for stat in upgrade_scrip_dir.glob("*.stats"):
stat.unlink()
codeql("dataset", "check", newdataset)
# compare tables
# as `codeql database diff` does not allow comparing DBs with different dbschemes, we just
# do the diff ourselves
tuples = extract_tuples(olddb, lang, dbschemename)
new_tuples = extract_tuples(newdb, lang, dbschemename)
for table in tuples:
tuples[table] = (tuples[table], new_tuples.pop(table, None))
for table, value in new_tuples.items():
tuples[table] = (None, value)
actual_lines = []
for table, (old, new) in sorted(tuples.items()):
size = len(actual_lines)
actual_lines.extend(difflib.unified_diff(
old or [],
new or [],
fromfile=f"old/{table}" if old is not None else "<created>",
tofile=f"new/{table}" if new is not None else "<deleted>",
n=0))
if len(actual_lines) > size:
actual_lines.append("\n")
# for this unified diff line numbers @@-lines are just noise
actual_lines[:] = [l for l in actual_lines if not l.startswith("@@")]
# manage .actual/.expected interactions
actual = test.with_suffix(".actual")
actual.unlink(missing_ok=True)
expected = test.with_suffix(".expected")
if not learn:
with open(expected) as expectedin:
expected_lines = expectedin.readlines()
diff = list(difflib.unified_diff(expected_lines, actual_lines, fromfile=str(expected), tofile=str(actual)))
if diff:
with open(actual, "w") as actualout:
actualout.writelines(actual_lines)
print("FAILURE")
raise Error(f"{test} FAILURE:\n{''.join(diff)}")
else:
print("SUCCESS")
else:
with open(expected, "w") as expectedout:
expectedout.writelines(actual_lines)
print("SUCCESS (results learned)")
def accept_test_results(test: pathlib.Path):
actual = test.with_suffix(".actual")
if actual.is_file():
actual.rename(test.with_suffix(".expected"))
print(f"=== {test} results accepted ===")
def main(opts: argparse.Namespace):
global verbose
verbose = opts.verbose
errors = []
for dir in opts.script_dirs:
if (dir / "upgrade.properties").is_file() and not (dir / "test").is_dir():
errors.append(Error(
f"testing of {dir.relative_to(dir.parents[1])} explicitly requested, but no test directory found"))
tests = collect_tests(opts.script_dirs)
if opts.accept:
for test, _ in tests:
accept_test_results(test)
else:
for test, lang in tests:
try:
run_test(test, lang, opts.learn)
except Error as e:
errors.append(e)
if errors:
for e in errors:
print(e, file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main(options())

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
description: Add YAML tables
compatibility: backwards
yaml.rel: delete
yaml_anchors.rel: delete
yaml_aliases.rel: delete
yaml_scalars.rel: delete
yaml_errors.rel: delete
yaml_locations.rel: delete

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added support for querying the contents of YAML files.

View File

@@ -9,5 +9,6 @@ dependencies:
codeql/regex: ${workspace}
codeql/tutorial: ${workspace}
codeql/util: ${workspace}
codeql/yaml: ${workspace}
dataExtensions:
- semmle/python/frameworks/**/model.yml

View File

@@ -8,6 +8,7 @@
import python
import semmle.python.RegexTreeView
import semmle.python.Yaml
private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
@@ -53,7 +54,9 @@ private newtype TPrintAstNode =
shouldPrint(list.getAnItem(), _) and
not list = any(Module mod).getBody() and
not forall(AstNode child | child = list.getAnItem() | isNotNeeded(child))
}
} or
TYamlNode(YamlNode node) or
TYamlMappingNode(YamlMapping mapping, int i) { exists(mapping.getKeyNode(i)) }
/**
* A node in the output tree.
@@ -633,6 +636,80 @@ private module PrettyPrinting {
}
}
/**
* Classes for printing YAML AST.
*/
module PrintYaml {
/**
* A print node representing a YAML value in a .yml file.
*/
class YamlNodeNode extends PrintAstNode, TYamlNode {
YamlNode node;
YamlNodeNode() { this = TYamlNode(node) }
override string toString() {
result = "[" + concat(node.getAPrimaryQlClass(), ",") + "] " + node.toString()
}
override Location getLocation() { result = node.getLocation() }
/**
* Gets the `YAMLNode` represented by this node.
*/
final YamlNode getValue() { result = node }
override PrintAstNode getChild(int childIndex) {
exists(YamlNode child | result.(YamlNodeNode).getValue() = child |
child = node.getChildNode(childIndex)
)
}
}
/**
* A print node representing a `YAMLMapping`.
*
* Each child of this node aggregates the key and value of a mapping.
*/
class YamlMappingNode extends YamlNodeNode {
override YamlMapping node;
override PrintAstNode getChild(int childIndex) {
exists(YamlMappingMapNode map | map = result | map.maps(node, childIndex))
}
}
/**
* A print node representing the `i`th mapping in `mapping`.
*/
class YamlMappingMapNode extends PrintAstNode, TYamlMappingNode {
YamlMapping mapping;
int i;
YamlMappingMapNode() { this = TYamlMappingNode(mapping, i) }
override string toString() {
result = "(Mapping " + i + ")" and not exists(mapping.getKeyNode(i).(YamlScalar).getValue())
or
result = "(Mapping " + i + ") " + mapping.getKeyNode(i).(YamlScalar).getValue() + ":"
}
/**
* Holds if this print node represents the `index`th mapping of `m`.
*/
predicate maps(YamlMapping m, int index) {
m = mapping and
index = i
}
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(YamlNodeNode).getValue() = mapping.getKeyNode(i)
or
childIndex = 1 and result.(YamlNodeNode).getValue() = mapping.getValueNode(i)
}
}
}
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
query predicate nodes(PrintAstNode node, string key, string value) { value = node.getProperty(key) }

View File

@@ -0,0 +1,50 @@
/**
* Provides classes for working with YAML data.
*
* YAML documents are represented as abstract syntax trees whose nodes
* are either YAML values or alias nodes referring to another YAML value.
*/
private import codeql.yaml.Yaml as LibYaml
private module YamlSig implements LibYaml::InputSig {
import semmle.python.Files
class LocatableBase extends @yaml_locatable {
Location getLocation() { yaml_locations(this, result) }
string toString() { none() }
}
class NodeBase extends LocatableBase, @yaml_node {
NodeBase getChildNode(int i) { yaml(result, _, this, i, _, _) }
string getTag() { yaml(this, _, _, _, result, _) }
string getAnchor() { yaml_anchors(this, result) }
override string toString() { yaml(this, _, _, _, _, result) }
}
class ScalarNodeBase extends NodeBase, @yaml_scalar_node {
int getStyle() { yaml_scalars(this, result, _) }
string getValue() { yaml_scalars(this, _, result) }
}
class CollectionNodeBase extends NodeBase, @yaml_collection_node { }
class MappingNodeBase extends CollectionNodeBase, @yaml_mapping_node { }
class SequenceNodeBase extends CollectionNodeBase, @yaml_sequence_node { }
class AliasNodeBase extends NodeBase, @yaml_alias_node {
string getTarget() { yaml_aliases(this, result) }
}
class ParseErrorBase extends LocatableBase, @yaml_error {
string getMessage() { yaml_errors(this, result) }
}
}
import LibYaml::Make<YamlSig>

View File

@@ -361,3 +361,52 @@ module MergePathGraph<
}
}
}
/**
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
*/
module MergePathGraph3<
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
{
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
private module Merged =
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
class PathNode instanceof Merged::PathNode {
/** Gets this as a projection on the first given `PathGraph`. */
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
/** Gets this as a projection on the second given `PathGraph`. */
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
/** Gets this as a projection on the third given `PathGraph`. */
PathNode3 asPathNode3() { result = super.asPathNode2() }
/** Gets a textual representation of this element. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
Node getNode() { result = super.getNode() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph = Merged::PathGraph;
}

View File

@@ -1200,6 +1200,7 @@ predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) {
* time the bound method is used, such that the `clear()` call would essentially be
* translated into `l.clear()`, and we can still have use-use flow.
*/
pragma[assume_small_delta]
cached
predicate getCallArg(CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos) {
Stages::DataFlow::ref() and

View File

@@ -1104,3 +1104,44 @@ xmllocations(int xmlElement: @xmllocatable ref,
int location: @location_default ref);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
/**
* YAML
*/
#keyset[parent, idx]
yaml (unique int id: @yaml_node,
int kind: int ref,
int parent: @yaml_node_parent ref,
int idx: int ref,
varchar(900) tag: string ref,
varchar(900) tostring: string ref);
case @yaml_node.kind of
0 = @yaml_scalar_node
| 1 = @yaml_mapping_node
| 2 = @yaml_sequence_node
| 3 = @yaml_alias_node
;
@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
@yaml_node_parent = @yaml_collection_node | @file;
yaml_anchors (unique int node: @yaml_node ref,
varchar(900) anchor: string ref);
yaml_aliases (unique int alias: @yaml_alias_node ref,
varchar(900) target: string ref);
yaml_scalars (unique int scalar: @yaml_scalar_node ref,
int style: int ref,
varchar(900) value: string ref);
yaml_errors (unique int id: @yaml_error,
varchar(900) message: string ref);
yaml_locations(unique int locatable: @yaml_locatable ref,
int location: @location_default ref);
@yaml_locatable = @yaml_node | @yaml_error;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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