Compare commits

..

140 Commits

Author SHA1 Message Date
Michael B. Gale
2bce3879db C#: Add test for TargetFramework install 2023-11-21 13:35:19 +00:00
Michael B. Gale
a126e1dfae C#: Fall back to TargetFramework to install .NET 2023-11-21 13:35:19 +00:00
Michael B. Gale
ebc4aaa3db C#: Load TargetFramework from project files 2023-11-21 13:32:06 +00:00
Michael B. Gale
373eb0a57e C#: Refactor code to read global.json version 2023-11-21 13:32:05 +00:00
Michael B. Gale
adde95d7a1 C#: Tolerate missing solution files in tests 2023-11-21 13:32:05 +00:00
Michael B. Gale
098812b073 C#: Add channel to DownloadDotNetVersion 2023-11-21 13:32:05 +00:00
Max Schaefer
ca334021ad Merge pull request #14793 from github/max-schaefer/tainted-path-qhelp
Java: Improve QHelp for `java/path-injection` to mention less disruptive fixes.
2023-11-16 14:09:55 +00:00
Stephan Brandauer
69ab389d9f Merge pull request #14795 from github/kaeluka/skip-this-qualifier-ctor-candidates
Java: Automodel Extraction: Remove Qualifier Endpoints of Constructors
2023-11-16 14:54:19 +01:00
Mathias Vorreiter Pedersen
30f0b8ab2b Merge pull request #14808 from jketema/jketema/del-fmt-global
C++: Delete `cpp/tainted-format-string-through-global`
2023-11-16 13:44:21 +00:00
Tom Hvitved
75f42f4614 Merge pull request #14783 from hvitved/ruby/hash-array-literal
Ruby: Include more nodes in `{Hash,Array}LiteralCfgNode`
2023-11-16 13:51:35 +01:00
Henry Mercer
0c1fb8c881 Merge pull request #14811 from github/henrymercer/remove-lines-of-non-user-code-from-summary
Remove LoC metrics from the analysis summary
2023-11-16 12:30:55 +00:00
Rasmus Wriedt Larsen
4f9303eb02 Merge pull request #14790 from RasmusWL/clean-tests
Python: Accept new ordering of query predicates in `.expected`
2023-11-16 13:23:35 +01:00
Tom Hvitved
2c23dacca1 Ruby: Add more hash/array literal tests 2023-11-16 12:58:53 +01:00
Max Schaefer
a5e7ef424e Revert "Add additional example."
This reverts commit 947b094387.
2023-11-16 11:54:16 +00:00
Stephan Brandauer
84e58b77aa Java Automodel: remove Qualifiers of constructors from endpoints 2023-11-16 12:44:53 +01:00
Stephan Brandauer
3092640115 Java Automodel: make test case for Argument[this] sink candidates in ctors in framework mode 2023-11-16 12:42:50 +01:00
Max Schaefer
143e1680bd Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2023-11-16 11:42:35 +00:00
Henry Mercer
de83929a60 Remove LoC metrics from the analysis summary 2023-11-16 11:36:44 +00:00
Stephan Brandauer
d7c97d9d92 Java Automodel: remove constructor instance arguments from endpoints and update test expectations 2023-11-16 12:27:23 +01:00
Stephan Brandauer
30925da7d9 Java Automodel: tests that demonstrate that there is no sink candidate of an object being constructed in app mode 2023-11-16 12:24:41 +01:00
Stephan Brandauer
f1001374fd Merge pull request #14642 from github/kaeluka/publish-automodel-querypack-007
Java: Publish Automodel query pack 0.0.7
2023-11-16 11:50:32 +01:00
Rasmus Wriedt Larsen
25d3af9236 Merge branch 'main' into clean-tests 2023-11-16 11:21:01 +01:00
Jeroen Ketema
1f3f1b5ec4 Merge pull request #14809 from MathiasVP/move-change-note
C++: Move change note
2023-11-16 11:14:14 +01:00
Max Schaefer
947b094387 Add additional example. 2023-11-16 10:06:19 +00:00
Max Schaefer
009d58034f Address suggestions from review. 2023-11-16 10:05:54 +00:00
Mathias Vorreiter Pedersen
5c0fb2030d C++: Move change note. 2023-11-16 09:57:08 +00:00
Jeroen Ketema
2eb67549e6 C++: Tweak change note slightly 2023-11-16 10:56:47 +01:00
Jeroen Ketema
afe318edbe C++: Delete cpp/tainted-format-string-through-global 2023-11-16 10:52:05 +01:00
Rasmus Wriedt Larsen
71ef98584d Merge pull request #14791 from RasmusWL/python-3.12
Python: Update `.expected` to support Python 3.12
2023-11-16 10:42:48 +01:00
Tom Hvitved
6bba191407 Merge pull request #14710 from hvitved/type-tracking/prepare-ruby
Prepare shared type tracking library for adoption by Ruby
2023-11-16 10:34:32 +01:00
Rasmus Wriedt Larsen
df144f3a1e Merge pull request #14406 from amammad/amammad-python-FileSystemAccess
Python: New FileSystem Access
2023-11-16 10:25:34 +01:00
Rasmus Wriedt Larsen
a46dc55e84 Merge branch 'main' into python-3.12 2023-11-16 09:34:06 +01:00
Tamás Vajk
14268f3c63 Merge pull request #14792 from tamasvajk/standalone/assembly-attribute
C#: Fix assembly attribute extraction in standalone mode
2023-11-16 08:09:14 +01:00
Sam Browning
408ba517e5 Merge pull request #14776 from github/sabrowning1/queries-panel-language-selector
Add content for the queries panel and language selector
2023-11-15 17:30:21 -05:00
Mathias Vorreiter Pedersen
4d4ca6b948 Merge pull request #14794 from MathiasVP/catch-more-return-stack-allocated-memory
C++: Catch more returns of stack-allocated memory
2023-11-15 19:23:24 +00:00
Sam Browning
d443354651 Apply feedback and fix syntax 2023-11-15 11:35:33 -05:00
Tom Hvitved
57f6859ddc Shared: Update type tracking consistency checks 2023-11-15 17:08:05 +01:00
Tom Hvitved
5f087f0084 Shared: Port features from Ruby's type tracking library to the shared library
- Cache relevant predicates.
- Expose some predicates and classes (only exposed internally).
- Make some top-level `inline_late` predicates member predicates.
- Actually eliminate type check in `flowsTo`.
- Fix bug in `getACompatibleTypeTracker`.
- Adopt the `CallGraphConstruction` module.
2023-11-15 17:08:05 +01:00
Tom Hvitved
f66f7ce8d7 Shared: Split up TypeTracking.qll into two files 2023-11-15 17:07:27 +01:00
Jeroen Ketema
f22979f4b6 Merge pull request #14561 from jketema/rewrite-uncontrolled-process-operation
C++: Rewrite `cpp/uncontrolled-process-operation` to not use `DefaultTaintTracking`
2023-11-15 16:03:58 +01:00
Jeroen Ketema
46e6e72593 C++: Address review comments 2023-11-15 14:57:53 +01:00
Jeroen Ketema
92c18960c5 C++: Rewrite cpp/uncontrolled-process-operation to not use DefaultTaintTracking 2023-11-15 14:57:53 +01:00
Rasmus Wriedt Larsen
e349891cff Python: Apply suggestions from code review 2023-11-15 14:35:52 +01:00
Rasmus Wriedt Larsen
e02c32f3d4 Python: options file was not enough, split into 2/3
I reckon this is due to the Python 3 version used by the Python 2 tests
is different from 3.12, so even with --lang=3 the tests are still using
an incompatible version :(
2023-11-15 14:24:11 +01:00
Rasmus Wriedt Larsen
0f1dc9b2d9 Python: Add missing options file 2023-11-15 13:24:08 +01:00
Rasmus Wriedt Larsen
ae6c95ff95 Python: Fix asyncio.coroutine deprecation
Was removed in 3.11, see https://docs.python.org/3.10/library/asyncio-task.html#asyncio.coroutine

I couldn't make the __awwait__ actually give the result to the agen function...

I also tried looking into
https://docs.python.org/3/library/types.html#types.coroutine, but also
failed to make that work.

Without the Future, such as doing `yield SOURCE` inside `__await__` it
complains `RuntimeError: Task got bad yield: 'source'`
2023-11-15 13:24:08 +01:00
Mathias Vorreiter Pedersen
bae7e10e46 C++: Also add MSVC-related 'alloca'-like functions. 2023-11-15 12:07:17 +00:00
Mathias Vorreiter Pedersen
ec63099c54 C++: Add change note. 2023-11-15 11:57:09 +00:00
Mathias Vorreiter Pedersen
2b8b5cf1b8 C++: Accept test changes. 2023-11-15 11:52:14 +00:00
Mathias Vorreiter Pedersen
6730f57d5c C++: Also flag up 'alloca' and friends. 2023-11-15 11:51:57 +00:00
Mathias Vorreiter Pedersen
118d50236f C++: Add failing tests. 2023-11-15 11:48:37 +00:00
Max Schaefer
a46a7fadb2 Java: Improve QHelp for java/path-injection to mention less disruptive fixes. 2023-11-15 11:25:13 +00:00
Tamas Vajk
7a001f4905 C#: Fix assembly attribute extraction in standalone mode 2023-11-15 12:21:03 +01:00
Owen Mansel-Chan
803ed20962 Merge pull request #14778 from owen-mc/go/improve-value-flow-through-arrays
Go: improve value flow through arrays
2023-11-15 11:13:15 +00:00
Rasmus Wriedt Larsen
4256fbf11a Python: Accept changes from Python 3.12 2023-11-15 11:42:38 +01:00
Rasmus Wriedt Larsen
f3dd002ba9 Python: Copy tests to Python 3 2023-11-15 11:42:38 +01:00
Rasmus Wriedt Larsen
f9e9ae91f7 Python: Move tests that would change under Python 3.12 to lang specific directory
This moves the tests to Python 2, next we copy them to Python 3.
2023-11-15 11:42:38 +01:00
Rasmus Wriedt Larsen
23419ee634 Python: Update .expected to support Python 3.12
You might wonder why the number of lines changed, but it's due to `tty`
module receiving its' first update since 2001, so the actual number of
lines DID change :phew:

https://github.com/python/cpython/commits/3.12/Lib/tty.py

Since there is now a difference between Python 2 and Python 3, we need to restrict the lines of code test to only run as Python 3.
2023-11-15 11:42:38 +01:00
Mathias Vorreiter Pedersen
b8f0f85840 Merge pull request #14784 from MathiasVP/no-dtt-in-tainted-arithmetic
C++: Rewrite `cpp/tainted-arithmetic` away from `DefaultTaintTracking`
2023-11-15 10:19:25 +00:00
Rasmus Wriedt Larsen
69453aa144 Python: Fix missing newline in .expected 2023-11-15 10:10:23 +01:00
Rasmus Wriedt Larsen
55f5b26ba6 Python: Accept new ordering of query predicates in .expected 2023-11-15 10:09:54 +01:00
Rasmus Wriedt Larsen
721bde1ce8 Python: Delete orphaned .expected files 2023-11-15 09:59:26 +01:00
Rasmus Wriedt Larsen
2e9d548083 Merge pull request #14706 from RasmusWL/class-attribute-flow
Python: Add basic flow for class attributes
2023-11-15 09:06:25 +01:00
Owen Mansel-Chan
83d1fc33e1 Add change note 2023-11-14 23:16:32 +00:00
Erik Krogh Kristensen
14e51627c5 Merge pull request #14419 from rvermeulen/rvermeulen/javascript-adjust-security-severity
JavaScript: Adjust XSS and log injection query severities
2023-11-14 21:34:25 +01:00
Remco Vermeulen
52540b42fc Merge branch 'main' into rvermeulen/javascript-adjust-security-severity 2023-11-14 11:21:38 -08:00
Remco Vermeulen
6bd7047e41 Restore XssThroughDom.ql's severity 2023-11-14 11:20:51 -08:00
AlexDenisov
57f1f5b829 Merge pull request #14768 from github/alexdenisov/move-semantics
Swift: extract AST nodes related to move semantics
2023-11-14 19:13:27 +01:00
Mathias Vorreiter Pedersen
bff93c4484 Merge branch 'main' into no-dtt-in-tainted-arithmetic 2023-11-14 17:12:34 +00:00
Geoffrey White
0342b3eba2 Merge pull request #14772 from geoffw0/webview
Swift: Use TaintInheritingContent in WebView.qll
2023-11-14 16:29:32 +00:00
Geoffrey White
d28e7920b3 Merge pull request #14773 from geoffw0/fixmodel
Swift: Fix odds and ends
2023-11-14 16:28:33 +00:00
Tamás Vajk
331ca61be9 Merge pull request #14789 from tamasvajk/autobuild/arm-nuget-restore
C#: Do not call nuget.exe on Apple Silicon
2023-11-14 17:13:42 +01:00
Alex Denisov
559b965e74 Swift: add change note 2023-11-14 16:11:28 +01:00
Felicity Chapman
6299b844f8 Merge pull request #14785 from github/felicitymay-security-severity
Update metadata-for-codeql-queries.rst
2023-11-14 14:13:53 +00:00
Sam Browning
4385b316c0 Apply feedback from code review 2023-11-14 09:10:07 -05:00
Sam Browning
b1dc6099ff Apply feedback from code review 2023-11-14 09:01:54 -05:00
Sam Browning
15099b3db0 Update docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2023-11-14 08:57:52 -05:00
Tamas Vajk
8334c6db91 C#: Do not call nuget.exe on Apple Silicon 2023-11-14 14:50:29 +01:00
Alex Denisov
1c75e5b2a6 Swift: add database migration scripts for move semantics 2023-11-14 14:35:58 +01:00
Mathias Vorreiter Pedersen
1623bba18a Merge branch 'main' into no-dtt-in-tainted-arithmetic 2023-11-14 13:35:15 +00:00
Tom Hvitved
475d8da342 Ruby: Include more nodes in {Hash,Array}LiteralCfgNode 2023-11-14 13:50:46 +01:00
Tom Hvitved
ae09499905 Merge pull request #14781 from hvitved/ruby/ssa-unitialized-to-string
Ruby: Include name of variable in `UninitializedDefinition.toString`
2023-11-14 13:49:27 +01:00
Mathias Vorreiter Pedersen
c950e26b3e C++: Rewrite 'cpp/cpp/tainted-arithmetic' away from DefaultTaintTracking. 2023-11-14 12:19:12 +00:00
Felicity Chapman
f75c062949 Update metadata-for-codeql-queries.rst
Replace link to blog with trackable GH.io link
2023-11-14 12:06:44 +00:00
Mathias Vorreiter Pedersen
f22d87b7c7 Merge pull request #14771 from MathiasVP/fix-missing-unbounded-write-results
C++: Fix missing results in `cpp/unbounded-write`
2023-11-14 12:03:13 +00:00
Tamás Vajk
e11a68803e Merge pull request #14782 from github/criemen/disable-int-test
Disable the nuget standalone dependencies test on ARM-osx.
2023-11-14 12:32:48 +01:00
Owen Mansel-Chan
45faed057c Improve SliceExpr documentation 2023-11-14 11:25:16 +00:00
Tom Hvitved
f1b67ade9b Ruby: Include name of variable in UninitializedDefinition.toString 2023-11-14 11:33:59 +01:00
Cornelius Riemenschneider
f9ae7c5454 Disable the nuget standalone dependencies test on ARM-osx.
The test is failing currently, and that needs further investigation.
This is a temporary workaround to allow us to continue to work on
some necessary infrastructure investments around these tests.
2023-11-14 11:13:55 +01:00
Geoffrey White
296dee90dd Merge remote-tracking branch 'upstream/main' into fixmodel 2023-11-14 09:38:14 +00:00
Mathias Vorreiter Pedersen
967bbbc1a7 C++: Block flow out of sinks that are qualifiers. This removes the new result duplication and keeps the new result. 2023-11-14 09:29:47 +00:00
Owen Mansel-Chan
c8779d0d0b Fix another test
No change in alerts, just 3 extra nodes.
2023-11-13 23:56:25 +00:00
Owen Mansel-Chan
28160e418c Update tests 2023-11-13 23:26:30 +00:00
Owen Mansel-Chan
ed349f7d6b Improve value flow through arrays 2023-11-13 23:26:16 +00:00
Sam Browning
fa569dcef4 Delete requirements.txt 2023-11-13 17:28:14 -05:00
Sam Browning
040d971588 Merge branch 'main' into sabrowning1/queries-panel-language-selector 2023-11-13 17:27:35 -05:00
Sam Browning
e95bfc816e Clarify that queries run against selected database 2023-11-13 17:15:41 -05:00
Sam Browning
44935cef63 Tweak for style 2023-11-13 17:08:31 -05:00
Sam Browning
190050f577 Tweak formatting and styling 2023-11-13 16:52:33 -05:00
Sam Browning
458baeff32 Add content on queries panel and language selector 2023-11-13 15:59:51 -05:00
Geoffrey White
5a451e964d Swift: Model mainDocumentURL. 2023-11-13 19:51:51 +00:00
Geoffrey White
b157d73c10 Swift: Make the URLRequest test more accurate. 2023-11-13 19:36:03 +00:00
Geoffrey White
985d1990eb Swift: Fix typo. 2023-11-13 18:55:11 +00:00
Geoffrey White
463096e4be Swift: Modernize tainted content in WebView.qll. 2023-11-13 18:30:40 +00:00
Geoffrey White
892beeab6d Swift: Add test case. 2023-11-13 18:25:59 +00:00
Geoffrey White
9ec2f9204b Swift: Correct components(separatedBy:) models. 2023-11-13 17:43:21 +00:00
Mathias Vorreiter Pedersen
c73e6f1fa8 C++: Accept more test changes. 2023-11-13 16:51:07 +00:00
Mathias Vorreiter Pedersen
9aafbfce13 C++: Fix test annotation. 2023-11-13 16:17:18 +00:00
Mathias Vorreiter Pedersen
cc6268339b C++: Fix failing test and accept test cases. 2023-11-13 15:57:22 +00:00
Mathias Vorreiter Pedersen
834b07e6ad C++: Add failing tests. 2023-11-13 15:54:41 +00:00
Alex Denisov
031f453af8 Swift: CFG for Copy/Consume expressions 2023-11-13 15:55:37 +01:00
Alex Denisov
002f2a0985 Swift: extract BorrowExpr 2023-11-13 15:55:37 +01:00
Alex Denisov
d21e27c717 Swift: extract ConsumeExpr 2023-11-13 15:55:37 +01:00
Alex Denisov
30e4822fb7 Swift: extract CopyExpr 2023-11-13 15:55:37 +01:00
Sam Browning
ed9a0ea155 Merge branch 'main' of https://github.com/github/codeql 2023-11-13 08:40:42 -05:00
Rasmus Wriedt Larsen
5fc8a00487 Python: Rename test function 2023-11-10 15:58:20 +01:00
Rasmus Wriedt Larsen
b3feb4d7e9 Update python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
Co-authored-by: yoff <lerchedahl@gmail.com>
2023-11-10 15:57:00 +01:00
Rasmus Wriedt Larsen
9b0ad8295e Python: Add test of nested classes 2023-11-08 14:58:40 +01:00
Rasmus Wriedt Larsen
9d5cf0b331 Merge branch 'main' into class-attribute-flow 2023-11-08 14:30:53 +01:00
Rasmus Wriedt Larsen
5433907c33 Python: Accept more test changes
All are for the better 🎉
2023-11-07 15:49:14 +01:00
Rasmus Wriedt Larsen
5bee44dcfe Python: add change-note 2023-11-07 11:27:11 +01:00
Rasmus Wriedt Larsen
6568332e3d Python: Add basic flow for class attributes 2023-11-07 11:23:42 +01:00
Rasmus Wriedt Larsen
6c50c2bfe6 Python: Highlight missing flow for class attributes 2023-11-07 11:23:42 +01:00
amammad
e8eff78799 fix tests because of error in Frameworks.qll 2023-11-06 19:19:36 +01:00
amammad
ad756d59c8 put new frameworks in Frameworks.qll and fix some mistakes of Baize 2023-11-06 19:17:50 +01:00
amammad
315bdc2b48 add tests for new frameworks 2023-11-06 19:13:57 +01:00
amammad
637c52d10a separate each new FileSystemAccess packages. 2023-11-06 19:03:55 +01:00
Rasmus Wriedt Larsen
92b13c4259 Merge branch 'main' into amammad-python-FileSystemAccess 2023-11-06 11:30:09 +01:00
Rasmus Wriedt Larsen
3d8a7e0ee3 Python: Add change-note 2023-11-06 11:29:52 +01:00
Sam Browning
225c96ec9f Merge branch 'main' of https://github.com/github/codeql 2023-11-03 09:42:55 -04:00
Sam Browning
37361d9f79 Merge branch 'main' of https://github.com/github/codeql 2023-11-01 11:43:33 -04:00
Stephan Brandauer
5385cc3aaa Merge branch 'main' into kaeluka/publish-automodel-querypack-007 2023-10-31 11:48:22 +01:00
Stephan Brandauer
9087259b1b Java: add instructions to automodel query publish script 2023-10-31 11:11:22 +01:00
Stephan Brandauer
968127eaa3 Java: release automodel extraction queries 0.0.7 2023-10-31 11:09:02 +01:00
amammad
a0e2e1ef21 add to Frameworks.qll 2023-10-21 19:49:27 +02:00
amammad
1fe565a46f cherrypy framework file system access Sinks are added 2023-10-21 19:47:30 +02:00
Remco Vermeulen
76e56cdac7 Adjust query severities 2023-10-09 12:52:09 -07:00
amammad
ad2631202d fix comments 2023-10-08 21:32:04 +02:00
amammad
6c8cc79b4d v1 2023-10-08 21:24:54 +02:00
Sam Browning
1a51c015b4 Add requirements.txt 2023-04-27 15:19:45 -04:00
407 changed files with 14531 additions and 1664 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The "Returning stack-allocated memory" (`cpp/return-stack-allocated-memory`) query now also detects returning stack-allocated memory allocated by calls to `alloca`, `strdupa`, and `strndupa`.

View File

@@ -27,16 +27,26 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
ReturnStackAllocatedMemoryConfig() { this = "ReturnStackAllocatedMemoryConfig" }
override predicate isSource(Instruction source) {
// Holds if `source` is a node that represents the use of a stack variable
exists(VariableAddressInstruction var, Function func |
var = source and
func = source.getEnclosingFunction() and
var.getAstVariable() instanceof StackVariable and
// Pointer-to-member types aren't properly handled in the dbscheme.
not var.getResultType() instanceof PointerToMemberType and
exists(Function func |
// Rule out FPs caused by extraction errors.
not any(ErrorExpr e).getEnclosingFunction() = func and
not intentionallyReturnsStackPointer(func)
not intentionallyReturnsStackPointer(func) and
func = source.getEnclosingFunction()
|
// `source` is an instruction that represents the use of a stack variable
exists(VariableAddressInstruction var |
var = source and
var.getAstVariable() instanceof StackVariable and
// Pointer-to-member types aren't properly handled in the dbscheme.
not var.getResultType() instanceof PointerToMemberType
)
or
// `source` is an instruction that represents the return value of a
// function that is known to return stack-allocated memory.
exists(Call call |
call.getTarget().hasGlobalName(["alloca", "strdupa", "strndupa", "_alloca", "_malloca"]) and
source.getUnconvertedResultExpression() = call
)
)
}
@@ -85,10 +95,10 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
}
from
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
MustFlowPathNode source, MustFlowPathNode sink, Instruction instr,
ReturnStackAllocatedMemoryConfig conf
where
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
source.getInstruction() = var
source.getInstruction() = instr
select sink.getInstruction(), source, sink, "May return stack-allocated memory from $@.",
var.getAst(), var.getAst().toString()
instr.getAst(), instr.getAst().toString()

View File

@@ -14,25 +14,47 @@
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.ir.IR
import Flow::PathGraph
predicate isProcessOperationExplanation(Expr arg, string processOperation) {
predicate isProcessOperationExplanation(DataFlow::Node arg, string processOperation) {
exists(int processOperationArg, FunctionCall call |
isProcessOperationArgument(processOperation, processOperationArg) and
call.getTarget().getName() = processOperation and
call.getArgument(processOperationArg) = arg
call.getArgument(processOperationArg) = [arg.asExpr(), arg.asIndirectExpr()]
)
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element arg) { isProcessOperationExplanation(arg, _) }
predicate isSource(FlowSource source, string sourceType) {
not source instanceof DataFlow::ExprNode and
sourceType = source.getSourceType()
}
from string processOperation, Expr arg, Expr source, PathNode sourceNode, PathNode sinkNode
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { isSource(node, _) }
predicate isSink(DataFlow::Node node) { isProcessOperationExplanation(node, _) }
predicate isBarrier(DataFlow::Node node) {
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
or
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
}
}
module Flow = TaintTracking::Global<Config>;
from
string processOperation, string sourceType, DataFlow::Node source, DataFlow::Node sink,
Flow::PathNode sourceNode, Flow::PathNode sinkNode
where
isProcessOperationExplanation(arg, processOperation) and
taintedWithPath(source, arg, sourceNode, sinkNode)
select arg, sourceNode, sinkNode,
source = sourceNode.getNode() and
sink = sinkNode.getNode() and
isSource(source, sourceType) and
isProcessOperationExplanation(sink, processOperation) and
Flow::flowPath(sourceNode, sinkNode)
select sink, sourceNode, sinkNode,
"The value of this argument may come from $@ and is being passed to " + processOperation + ".",
source, source.toString()
source, sourceType

View File

@@ -52,16 +52,17 @@ predicate isUnboundedWrite(BufferWrite bw) {
* Holds if `e` is a source buffer going into an unbounded write `bw` or a
* qualifier of (a qualifier of ...) such a source.
*/
predicate unboundedWriteSource(Expr e, BufferWrite bw) {
isUnboundedWrite(bw) and e = bw.getASource()
predicate unboundedWriteSource(Expr e, BufferWrite bw, boolean qualifier) {
isUnboundedWrite(bw) and e = bw.getASource() and qualifier = false
or
exists(FieldAccess fa | unboundedWriteSource(fa, bw) and e = fa.getQualifier())
exists(FieldAccess fa | unboundedWriteSource(fa, bw, _) and e = fa.getQualifier()) and
qualifier = true
}
predicate isSource(FS::FlowSource source, string sourceType) { source.getSourceType() = sourceType }
predicate isSink(DataFlow::Node sink, BufferWrite bw) {
unboundedWriteSource(sink.asIndirectExpr(), bw)
predicate isSink(DataFlow::Node sink, BufferWrite bw, boolean qualifier) {
unboundedWriteSource(sink.asIndirectExpr(), bw, qualifier)
or
// `gets` and `scanf` reads from stdin so there's no real input.
// The `BufferWrite` library models this as the call itself being
@@ -69,7 +70,7 @@ predicate isSink(DataFlow::Node sink, BufferWrite bw) {
// the sink so that we report a path where source = sink (because
// the same output argument is also included in `isSource`).
bw.getASource() = bw and
unboundedWriteSource(sink.asDefiningArgument(), bw)
unboundedWriteSource(sink.asDefiningArgument(), bw, qualifier)
}
predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
@@ -84,9 +85,9 @@ predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
predicate isBarrierOut(DataFlow::Node node) { isSink(node) }
predicate isBarrierOut(DataFlow::Node node) { isSink(node, _, false) }
predicate isBarrier(DataFlow::Node node) {
// Block flow if the node is guarded by any <, <= or = operations.
@@ -116,7 +117,7 @@ from BufferWrite bw, Flow::PathNode source, Flow::PathNode sink, string sourceTy
where
Flow::flowPath(source, sink) and
isSource(source.getNode(), sourceType) and
isSink(sink.getNode(), bw)
isSink(sink.getNode(), bw, _)
select bw, source, sink,
"This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.",
source.getNode(), sourceType

View File

@@ -1,24 +0,0 @@
#include <stdio.h>
char *copy;
void copyArgv(char **argv) {
copy = argv[1];
}
void printWrapper(char *str) {
printf(str);
}
int main(int argc, char **argv) {
copyArgv(argv);
// This should be avoided
printf(copy);
// This should be avoided too, because it has the same effect
printWrapper(copy);
// This is fine
printf("%s", copy);
}

View File

@@ -1,36 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The program uses input from the user, propagated via a global variable, as a format string for <code>printf</code> style functions.
This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program,
disclose information or even execute arbitrary code.</p>
<p>This rule only identifies inputs from the user that are transferred through global variables before being used in <code>printf</code> style functions.
Analyzing the flow of data through global variables is more prone to errors and so this rule may identify some examples of code where
the input is not really from the user. For example, when a global variable is set in two places, one that comes from the user and one that does not.
In this case we would mark all usages of the global variable as input from the user, but the input from the user may always came after the call to the
<code>printf</code> style functions.</p>
<p>The results of this rule should be considered alongside the related rule "Uncontrolled format string" which tracks the flow of the
values input by a user, excluding global variables, until the values are used as the format argument for a <code>printf</code> like function call.</p>
</overview>
<recommendation>
<p>Use constant expressions as the format strings. If you need to print a value from the user, use <code>printf("%s", value_from_user)</code>.</p>
</recommendation>
<example>
<sample src="UncontrolledFormatStringThroughGlobalVar.c" />
</example>
<references>
<li>CERT C Coding
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude
user input from format strings</a>.</li>
</references>
</qhelp>

View File

@@ -1,40 +0,0 @@
/**
* @name Uncontrolled format string (through global variable)
* @description Using externally-controlled format strings in
* printf-style functions can lead to buffer overflows
* or data representation problems.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision high
* @id cpp/tainted-format-string-through-global
* @tags reliability
* security
* external/cwe/cwe-134
*/
import cpp
import semmle.code.cpp.security.FunctionWithWrappers
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) {
exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _))
}
override predicate taintThroughGlobals() { any() }
}
from
PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode,
string printfFunction, Expr userValue, string cause
where
printf.outermostWrapperFunctionCall(arg, printfFunction) and
not taintedWithoutGlobals(arg) and
taintedWithPath(userValue, arg, sourceNode, sinkNode) and
isUserInput(userValue, cause)
select arg, sourceNode, sinkNode,
"The value of this argument may come from $@ and is being used as a formatting argument to " +
printfFunction + ".", userValue, cause

View File

@@ -14,10 +14,13 @@
import cpp
import semmle.code.cpp.security.Overflow
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards as IRGuards
import semmle.code.cpp.security.FlowSources as FS
import Bounded
import Flow::PathGraph
bindingset[op]
predicate missingGuard(Operation op, Expr e, string effect) {
@@ -28,28 +31,90 @@ predicate missingGuard(Operation op, Expr e, string effect) {
not e instanceof VariableAccess and effect = "overflow"
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element e) {
exists(Operation op |
missingGuard(op, e, _) and
op.getAnOperand() = e
|
op instanceof UnaryArithmeticOperation or
op instanceof BinaryArithmeticOperation or
op instanceof AssignArithmeticOperation
)
}
predicate isSource(FS::FlowSource source, string sourceType) { sourceType = source.getSourceType() }
override predicate isBarrier(Expr e) {
super.isBarrier(e) or bounded(e) or e.getUnspecifiedType().(IntegralType).getSize() <= 1
predicate isSink(DataFlow::Node sink, Operation op, Expr e) {
e = sink.asExpr() and
missingGuard(op, e, _) and
op.getAnOperand() = e and
(
op instanceof UnaryArithmeticOperation or
op instanceof BinaryArithmeticOperation or
op instanceof AssignArithmeticOperation
)
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate constantInstruction(Instruction instr) {
instr instanceof ConstantInstruction or
constantInstruction(instr.(UnaryInstruction).getUnary())
}
predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
exists(Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
any(IRGuards::IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
)
}
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
predicate isBarrier(DataFlow::Node node) {
exists(StoreInstruction store | store = node.asInstruction() |
// Block flow to "likely small expressions"
bounded(store.getSourceValue().getUnconvertedResultExpression())
or
// Block flow to "small types"
store.getResultType().getUnspecifiedType().(IntegralType).getSize() <= 1
)
or
// Block flow if there's an upper bound check of the variable anywhere in the program
exists(Variable checkedVar, Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
// Block flow if the node is guarded by an equality check
exists(Variable checkedVar, Operand access |
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
readsVariable(access.getDef(), checkedVar)
)
or
// Block flow to any binary instruction whose operands are both non-constants.
exists(BinaryInstruction iTo |
iTo = node.asInstruction() and
not constantInstruction(iTo.getLeft()) and
not constantInstruction(iTo.getRight()) and
// propagate taint from either the pointer or the offset, regardless of constantness
not iTo instanceof PointerArithmeticInstruction
)
}
}
from Expr origin, Expr e, string effect, PathNode sourceNode, PathNode sinkNode, Operation op
module Flow = TaintTracking::Global<Config>;
from
Expr e, string effect, Flow::PathNode source, Flow::PathNode sink, Operation op, string sourceType
where
taintedWithPath(origin, e, sourceNode, sinkNode) and
op.getAnOperand() = e and
Flow::flowPath(source, sink) and
isSource(source.getNode(), sourceType) and
isSink(sink.getNode(), op, e) and
missingGuard(op, e, effect)
select e, sourceNode, sinkNode,
select e, source, sink,
"$@ flows to an operand of an arithmetic expression, potentially causing an " + effect + ".",
origin, "User-provided value"
source, sourceType

View File

@@ -4,6 +4,7 @@
* @description The total number of lines of C/C++ code across all files, including system headers, libraries, and auto-generated files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
* telemetry
*/
import cpp

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* The `cpp/tainted-format-string-through-global` query has been deleted. This does not lead to a loss of relevant alerts, as the query duplicated a subset of the alerts from `cpp/tainted-format-string`.

View File

@@ -43,6 +43,11 @@ edges
| test.cpp:189:16:189:16 | p | test.cpp:189:16:189:16 | (reference to) |
| test.cpp:190:10:190:13 | (reference dereference) | test.cpp:190:10:190:13 | (reference to) |
| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | (reference dereference) |
| test.cpp:237:12:237:17 | call to alloca | test.cpp:237:12:237:17 | call to alloca |
| test.cpp:237:12:237:17 | call to alloca | test.cpp:238:9:238:9 | p |
| test.cpp:249:13:249:20 | call to strndupa | test.cpp:249:13:249:20 | call to strndupa |
| test.cpp:249:13:249:20 | call to strndupa | test.cpp:250:9:250:10 | s2 |
| test.cpp:250:9:250:10 | s2 | test.cpp:250:9:250:10 | (void *)... |
nodes
| test.cpp:17:9:17:11 | & ... | semmle.label | & ... |
| test.cpp:17:10:17:11 | mc | semmle.label | mc |
@@ -101,6 +106,14 @@ nodes
| test.cpp:190:10:190:13 | (reference dereference) | semmle.label | (reference dereference) |
| test.cpp:190:10:190:13 | (reference to) | semmle.label | (reference to) |
| test.cpp:190:10:190:13 | pRef | semmle.label | pRef |
| test.cpp:237:12:237:17 | call to alloca | semmle.label | call to alloca |
| test.cpp:237:12:237:17 | call to alloca | semmle.label | call to alloca |
| test.cpp:238:9:238:9 | p | semmle.label | p |
| test.cpp:245:9:245:15 | call to strdupa | semmle.label | call to strdupa |
| test.cpp:249:13:249:20 | call to strndupa | semmle.label | call to strndupa |
| test.cpp:249:13:249:20 | call to strndupa | semmle.label | call to strndupa |
| test.cpp:250:9:250:10 | (void *)... | semmle.label | (void *)... |
| test.cpp:250:9:250:10 | s2 | semmle.label | s2 |
#select
| test.cpp:17:9:17:11 | CopyValue: & ... | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | & ... | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
| test.cpp:25:9:25:11 | Load: ptr | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | ptr | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |
@@ -115,3 +128,6 @@ nodes
| test.cpp:177:10:177:23 | Convert: (void *)... | test.cpp:176:25:176:34 | localArray | test.cpp:177:10:177:23 | (void *)... | May return stack-allocated memory from $@. | test.cpp:176:25:176:34 | localArray | localArray |
| test.cpp:183:10:183:19 | CopyValue: (reference to) | test.cpp:182:21:182:27 | myLocal | test.cpp:183:10:183:19 | (reference to) | May return stack-allocated memory from $@. | test.cpp:182:21:182:27 | myLocal | myLocal |
| test.cpp:190:10:190:13 | CopyValue: (reference to) | test.cpp:189:16:189:16 | p | test.cpp:190:10:190:13 | (reference to) | May return stack-allocated memory from $@. | test.cpp:189:16:189:16 | p | p |
| test.cpp:238:9:238:9 | Load: p | test.cpp:237:12:237:17 | call to alloca | test.cpp:238:9:238:9 | p | May return stack-allocated memory from $@. | test.cpp:237:12:237:17 | call to alloca | call to alloca |
| test.cpp:245:9:245:15 | Call: call to strdupa | test.cpp:245:9:245:15 | call to strdupa | test.cpp:245:9:245:15 | call to strdupa | May return stack-allocated memory from $@. | test.cpp:245:9:245:15 | call to strdupa | call to strdupa |
| test.cpp:250:9:250:10 | Convert: (void *)... | test.cpp:249:13:249:20 | call to strndupa | test.cpp:250:9:250:10 | (void *)... | May return stack-allocated memory from $@. | test.cpp:249:13:249:20 | call to strndupa | call to strndupa |

View File

@@ -229,4 +229,23 @@ int* id(int* px) {
void f() {
int x;
int* px = id(&x); // GOOD
}
void *alloca(size_t);
void* test_alloca() {
void* p = alloca(10);
return p; // BAD
}
char *strdupa(const char *);
char *strndupa(const char *, size_t);
char* test_strdupa(const char* s) {
return strdupa(s); // BAD
}
void* test_strndupa(const char* s, size_t size) {
char* s2 = strndupa(s, size);
return s2; // BAD
}

View File

@@ -1,23 +1,12 @@
edges
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
| test.cpp:73:24:73:27 | data | test.cpp:37:73:37:76 | data |
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data indirection |
| test.cpp:64:30:64:35 | call to getenv indirection | test.cpp:73:24:73:27 | data indirection |
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | data indirection |
subpaths
nodes
| test.cpp:37:73:37:76 | data | semmle.label | data |
| test.cpp:37:73:37:76 | data indirection | semmle.label | data indirection |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:73:24:73:27 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
| test.cpp:64:30:64:35 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:73:24:73:27 | data indirection | semmle.label | data indirection |
subpaths
#select
| test.cpp:43:32:43:35 | data | test.cpp:64:30:64:35 | call to getenv | test.cpp:43:32:43:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA. | test.cpp:64:30:64:35 | call to getenv | call to getenv |
| test.cpp:43:32:43:35 | data indirection | test.cpp:64:30:64:35 | call to getenv indirection | test.cpp:43:32:43:35 | data indirection | The value of this argument may come from $@ and is being passed to LoadLibraryA. | test.cpp:64:30:64:35 | call to getenv indirection | an environment variable |

View File

@@ -1,112 +1,48 @@
edges
| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command |
| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command |
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
| test.cpp:42:18:42:23 | call to getenv | test.cpp:24:30:24:36 | command |
| test.cpp:42:18:42:34 | call to getenv | test.cpp:24:30:24:36 | command |
| test.cpp:43:18:43:23 | call to getenv | test.cpp:29:30:29:36 | command |
| test.cpp:43:18:43:34 | call to getenv | test.cpp:29:30:29:36 | command |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
subpaths
| test.cpp:24:30:24:36 | command indirection | test.cpp:26:10:26:16 | command indirection |
| test.cpp:29:30:29:36 | command indirection | test.cpp:31:10:31:16 | command indirection |
| test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:24:30:24:36 | command indirection |
| test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | command indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection |
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection |
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection |
| test.cpp:113:8:113:12 | call to fgets indirection | test.cpp:114:9:114:11 | ptr indirection |
nodes
| test.cpp:24:30:24:36 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:29:30:29:36 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:42:18:42:34 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:34 | call to getenv | semmle.label | call to getenv |
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
| test.cpp:24:30:24:36 | command indirection | semmle.label | command indirection |
| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection |
| test.cpp:29:30:29:36 | command indirection | semmle.label | command indirection |
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
| test.cpp:42:18:42:34 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:43:18:43:34 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:64:10:64:16 | (reference dereference) indirection | semmle.label | (reference dereference) indirection |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:98:17:98:22 | recv output argument | semmle.label | recv output argument |
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:106:17:106:22 | recv output argument | semmle.label | recv output argument |
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
| test.cpp:113:8:113:12 | call to fgets | semmle.label | call to fgets |
| test.cpp:113:8:113:12 | call to fgets | semmle.label | call to fgets |
| test.cpp:114:9:114:11 | ptr | semmle.label | ptr |
| test.cpp:114:9:114:11 | ptr | semmle.label | ptr |
| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:113:8:113:12 | call to fgets indirection | semmle.label | call to fgets indirection |
| test.cpp:114:9:114:11 | ptr indirection | semmle.label | ptr indirection |
subpaths
#select
| test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:23 | call to getenv | call to getenv |
| test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:23 | call to getenv | call to getenv |
| test.cpp:62:10:62:15 | buffer | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:63:10:63:13 | data | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:64:10:64:16 | dataref | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:65:10:65:14 | data2 | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:78:10:78:15 | buffer | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | buffer | buffer |
| test.cpp:99:15:99:20 | buffer | test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:98:17:98:22 | buffer | buffer |
| test.cpp:107:15:107:20 | buffer | test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:106:17:106:22 | buffer | buffer |
| test.cpp:114:9:114:11 | ptr | test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr | The value of this argument may come from $@ and is being passed to system. | test.cpp:113:8:113:12 | call to fgets | call to fgets |
| test.cpp:26:10:26:16 | command indirection | test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:26:10:26:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:34 | call to getenv indirection | an environment variable |
| test.cpp:31:10:31:16 | command indirection | test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:31:10:31:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:34 | call to getenv indirection | an environment variable |
| test.cpp:62:10:62:15 | buffer indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:63:10:63:13 | data indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:64:10:64:16 | (reference dereference) indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:64:10:64:16 | dataref indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:65:10:65:14 | data2 indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:78:10:78:15 | buffer indirection | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | fgets output argument | string read by fgets |
| test.cpp:99:15:99:20 | buffer indirection | test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:98:17:98:22 | recv output argument | buffer read by recv |
| test.cpp:107:15:107:20 | buffer indirection | test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:106:17:106:22 | recv output argument | buffer read by recv |
| test.cpp:114:9:114:11 | ptr indirection | test.cpp:113:8:113:12 | call to fgets indirection | test.cpp:114:9:114:11 | ptr indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:113:8:113:12 | call to fgets indirection | string read by fgets |

View File

@@ -1,16 +1,32 @@
edges
| main.cpp:6:27:6:30 | argv indirection | main.cpp:10:20:10:23 | argv indirection |
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:618:32:618:35 | argv indirection |
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:631:32:631:35 | argv indirection |
| tests.cpp:613:19:613:24 | source indirection | tests.cpp:615:17:615:22 | source indirection |
| tests.cpp:618:32:618:35 | argv indirection | tests.cpp:643:9:643:15 | access to array indirection |
| tests.cpp:643:9:643:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
| tests.cpp:622:19:622:24 | source indirection | tests.cpp:625:2:625:16 | ... = ... indirection |
| tests.cpp:625:2:625:16 | ... = ... indirection | tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] |
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | tests.cpp:628:14:628:14 | s indirection [home indirection] |
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:14:628:19 | home indirection |
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:16:628:19 | home indirection |
| tests.cpp:628:16:628:19 | home indirection | tests.cpp:628:14:628:19 | home indirection |
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:656:9:656:15 | access to array indirection |
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:657:9:657:15 | access to array indirection |
| tests.cpp:656:9:656:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
| tests.cpp:657:9:657:15 | access to array indirection | tests.cpp:622:19:622:24 | source indirection |
nodes
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
| main.cpp:10:20:10:23 | argv indirection | semmle.label | argv indirection |
| tests.cpp:613:19:613:24 | source indirection | semmle.label | source indirection |
| tests.cpp:615:17:615:22 | source indirection | semmle.label | source indirection |
| tests.cpp:618:32:618:35 | argv indirection | semmle.label | argv indirection |
| tests.cpp:643:9:643:15 | access to array indirection | semmle.label | access to array indirection |
| tests.cpp:622:19:622:24 | source indirection | semmle.label | source indirection |
| tests.cpp:625:2:625:16 | ... = ... indirection | semmle.label | ... = ... indirection |
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | semmle.label | s indirection [post update] [home indirection] |
| tests.cpp:628:14:628:14 | s indirection [home indirection] | semmle.label | s indirection [home indirection] |
| tests.cpp:628:14:628:19 | home indirection | semmle.label | home indirection |
| tests.cpp:628:16:628:19 | home indirection | semmle.label | home indirection |
| tests.cpp:631:32:631:35 | argv indirection | semmle.label | argv indirection |
| tests.cpp:656:9:656:15 | access to array indirection | semmle.label | access to array indirection |
| tests.cpp:657:9:657:15 | access to array indirection | semmle.label | access to array indirection |
subpaths
#select
| tests.cpp:615:2:615:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:615:17:615:22 | source indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |
| tests.cpp:628:2:628:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:628:14:628:19 | home indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |

View File

@@ -615,6 +615,19 @@ void test24(char* source) {
strcpy(buffer, source); // BAD
}
struct my_struct {
char* home;
};
void test25(char* source) {
my_struct s;
s.home = source;
char buf[100];
strcpy(buf, s.home); // BAD
}
int tests_main(int argc, char *argv[])
{
long long arr17[19];
@@ -641,6 +654,7 @@ int tests_main(int argc, char *argv[])
test22(argc == 0, argv[0]);
test23();
test24(argv[0]);
test25(argv[0]);
return 0;
}

View File

@@ -1,69 +0,0 @@
edges
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:33:15:33:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:44:15:44:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:11:22:11:25 | argv | globalVars.c:8:7:8:10 | copy |
| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | ... = ... |
| globalVars.c:12:2:12:15 | ... = ... | globalVars.c:8:7:8:10 | copy |
| globalVars.c:15:21:15:23 | val | globalVars.c:9:7:9:11 | copy2 |
| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | ... = ... |
| globalVars.c:16:2:16:12 | ... = ... | globalVars.c:9:7:9:11 | copy2 |
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
subpaths
nodes
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 |
| globalVars.c:11:22:11:25 | argv | semmle.label | argv |
| globalVars.c:12:2:12:15 | ... = ... | semmle.label | ... = ... |
| globalVars.c:15:21:15:23 | val | semmle.label | val |
| globalVars.c:16:2:16:12 | ... = ... | semmle.label | ... = ... |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:33:15:33:18 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
#select
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |

View File

@@ -1 +0,0 @@
Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql

View File

@@ -1,13 +1,8 @@
edges
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
subpaths
nodes
| examples.cpp:63:26:63:30 | & ... | semmle.label | & ... |
| examples.cpp:63:26:63:30 | fscanf output argument | semmle.label | fscanf output argument |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
subpaths
#select
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | & ... | User-provided value |
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | fscanf output argument | value read by fscanf |

View File

@@ -1,86 +1,59 @@
edges
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
| test2.cpp:25:22:25:23 | & ... | test2.cpp:27:13:27:13 | v |
| test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:13:27:13 | v |
| test2.cpp:27:13:27:13 | v | test2.cpp:12:21:12:21 | v |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt |
| test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections |
| test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 |
| test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:18:6:18:18 | call to getTaintedInt |
| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection |
| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection |
| test5.cpp:9:7:9:9 | gets output argument | test5.cpp:5:5:5:17 | getTaintedInt indirection |
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y |
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
subpaths
| test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections |
| test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 |
| test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 |
nodes
| test2.cpp:12:21:12:21 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:25:22:25:23 | & ... | semmle.label | & ... |
| test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument |
| test2.cpp:27:13:27:13 | v | semmle.label | v |
| test2.cpp:36:9:36:14 | buffer | semmle.label | buffer |
| test2.cpp:36:9:36:14 | buffer | semmle.label | buffer |
| test2.cpp:36:9:36:14 | fgets output argument | semmle.label | fgets output argument |
| test2.cpp:39:9:39:11 | num | semmle.label | num |
| test2.cpp:39:9:39:11 | num | semmle.label | num |
| test2.cpp:40:3:40:5 | num | semmle.label | num |
| test2.cpp:40:3:40:5 | num | semmle.label | num |
| test3.c:10:27:10:30 | argv indirection | semmle.label | argv indirection |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | semmle.label | getTaintedInt indirection |
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test.c:11:29:11:32 | argv | semmle.label | argv |
| test.c:11:29:11:32 | argv | semmle.label | argv |
| test.c:10:27:10:30 | argv indirection | semmle.label | argv indirection |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:41:17:41:20 | argv | semmle.label | argv |
| test.c:41:17:41:20 | argv | semmle.label | argv |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:51:17:51:20 | argv | semmle.label | argv |
| test.c:51:17:51:20 | argv | semmle.label | argv |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
subpaths
#select
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:39:9:39:11 | num | test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
| test2.cpp:40:3:40:5 | num | test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | buf | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | buf | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | buf | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test.c:14:15:14:28 | maxConnections | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:14:15:14:28 | maxConnections | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:44:7:44:10 | len2 | test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:41:17:41:20 | argv | User-provided value |
| test.c:54:7:54:10 | len3 | test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:51:17:51:20 | argv | User-provided value |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:39:9:39:11 | num | test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test2.cpp:40:3:40:5 | num | test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |

View File

@@ -559,6 +559,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.sln"] = false;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
@@ -573,6 +574,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone"] = 10;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.sln"] = false;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
@@ -587,6 +589,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone foo.sln"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["foo.sln"] = false;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
@@ -629,6 +632,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess["./build.sh --skip-tests"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.sln"] = false;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
@@ -729,6 +733,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"cmd.exe /C C:\codeql\tools\java\bin\java -jar C:\codeql\csharp\tools\extractor-asp.jar ."] = 0;
actions.RunProcess[@"cmd.exe /C C:\codeql\tools\codeql index --xml --extensions config"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.sln"] = false;
SkipVsWhere();
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -875,6 +880,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone foo.sln --skip-nuget"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["foo.sln"] = false;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
@@ -946,6 +952,40 @@ namespace Semmle.Autobuild.CSharp.Tests
TestAutobuilderScript(autobuilder, 0, 8);
}
[Fact]
public void TestDotnetVersionInstalledFromTargetFramework()
{
actions.RunProcess["dotnet --list-sdks"] = 0;
actions.RunProcessOut["dotnet --list-sdks"] = "6.0.404 [C:\\Program Files\\dotnet\\sdks]\n7.0.102 [C:\\Program Files\\dotnet\\sdks]";
actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0;
actions.RunProcess[@"./dotnet-install.sh --channel 8.0 --version latest --install-dir C:\Project/.dotnet"] = 0;
actions.RunProcess[@"rm dotnet-install.sh"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.GetEnvironmentVariable["PATH"] = "/bin:/usr/bin";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs\ntest.csproj";
actions.EnumerateDirectories[@"C:\Project"] = "";
var xml = new XmlDocument();
xml.LoadXml(@"<Project Sdk=""Microsoft.NET.Sdk"">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>");
actions.LoadXml[@"C:\Project/test.csproj"] = xml;
actions.DownloadFiles.Add(("https://dot.net/v1/dotnet-install.sh", "dotnet-install.sh"));
var autobuilder = CreateAutoBuilder(false);
TestAutobuilderScript(autobuilder, 0, 8);
}
[Fact]
public void TestDotnetVersionAlreadyInstalled()
{
@@ -1016,7 +1056,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
TestDotnetVersionWindows(() =>
{
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel release -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
},
6);
}
@@ -1026,8 +1066,8 @@ namespace Semmle.Autobuild.CSharp.Tests
{
TestDotnetVersionWindows(() =>
{
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 1;
actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel release -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 1;
actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel release -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
},
7);
}

View File

@@ -119,20 +119,13 @@ namespace Semmle.Autobuild.CSharp
=> WithDotNet(builder, (_1, env) => f(env));
/// <summary>
/// Returns a script for downloading relevant versions of the
/// .NET Core SDK. The SDK(s) will be installed at <code>installDir</code>
/// (provided that the script succeeds).
/// Tries to determine the version of .NET that's required for the project from a <code>global.json</code> file, if present.
/// </summary>
private static BuildScript DownloadDotNet(IAutobuilder<AutobuildOptionsShared> builder, string installDir)
/// <returns>
/// Returns the .NET version specified in <code>global.json<code> as a string or null if no version could be retrieved.
/// </returns>
private static string? SdkVersionFromGlobalJson(IAutobuilder<AutobuildOptionsShared> builder)
{
if (!string.IsNullOrEmpty(builder.Options.DotNetVersion))
// Specific version supplied in configuration: always use that
return DownloadDotNetVersion(builder, installDir, builder.Options.DotNetVersion);
// Download versions mentioned in `global.json` files
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
var installScript = BuildScript.Success;
var validGlobalJson = false;
foreach (var path in builder.Paths.Select(p => p.Item1).Where(p => p.EndsWith("global.json", StringComparison.Ordinal)))
{
string version;
@@ -147,11 +140,59 @@ namespace Semmle.Autobuild.CSharp
continue;
}
installScript &= DownloadDotNetVersion(builder, installDir, version);
validGlobalJson = true;
return version;
}
return validGlobalJson ? installScript : BuildScript.Failure;
return null;
}
/// <summary>
/// Returns a script for downloading relevant versions of the
/// .NET Core SDK. The SDK(s) will be installed at <code>installDir</code>
/// (provided that the script succeeds).
/// </summary>
private static BuildScript DownloadDotNet(IAutobuilder<AutobuildOptionsShared> builder, string installDir)
{
if (!string.IsNullOrEmpty(builder.Options.DotNetVersion))
// Specific version supplied in configuration: always use that
return DownloadDotNetVersion(builder, installDir, builder.Options.DotNetVersion);
// Download versions mentioned in `global.json` files
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
var installScript = BuildScript.Success;
var foundFrameworkVersion = false;
var globalJsonSdkVersion = SdkVersionFromGlobalJson(builder);
if (!string.IsNullOrEmpty(globalJsonSdkVersion))
{
installScript &= DownloadDotNetVersion(builder, installDir, globalJsonSdkVersion);
foundFrameworkVersion = true;
}
else
{
// If there is no `global.json` to retrieve the .NET version from, we find all the
// TargetFramework values in the project files and install the latest versions
// from the corresponding channels
var targetFrameworkVersions = builder.ProjectsOrSolutionsToBuild
.SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects))
.OfType<Project<CSharpAutobuildOptions>>()
.Select(p => p.TargetFramework)
.OfType<string>()
.Where(v => v.StartsWith("net"));
foreach (var targetFrameworkVersion in targetFrameworkVersions)
{
// For simplicity, we only accept target frameworks of the form "netX.Y"
Version? version = null;
if (Version.TryParse(targetFrameworkVersion[3..], out version))
{
installScript &= DownloadDotNetVersion(builder, installDir, "latest", channel: version.ToString());
foundFrameworkVersion = true;
}
}
}
return foundFrameworkVersion ? installScript : BuildScript.Failure;
}
/// <summary>
@@ -160,7 +201,7 @@ namespace Semmle.Autobuild.CSharp
///
/// See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
/// </summary>
private static BuildScript DownloadDotNetVersion(IAutobuilder<AutobuildOptionsShared> builder, string path, string version)
private static BuildScript DownloadDotNetVersion(IAutobuilder<AutobuildOptionsShared> builder, string path, string version, string? channel = "release")
{
return BuildScript.Bind(GetInstalledSdksScript(builder.Actions), (sdks, sdksRet) =>
{
@@ -174,7 +215,7 @@ namespace Semmle.Autobuild.CSharp
if (builder.Actions.IsWindows())
{
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version {version} -InstallDir {path}";
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel {channel} -Version {version} -InstallDir {path}";
BuildScript GetInstall(string pwsh) =>
new CommandBuilder(builder.Actions).
@@ -203,7 +244,7 @@ namespace Semmle.Autobuild.CSharp
var install = new CommandBuilder(builder.Actions).
RunCommand("./dotnet-install.sh").
Argument("--channel").
Argument("release").
Argument(channel).
Argument("--version").
Argument(version).
Argument("--install-dir").

View File

@@ -82,7 +82,12 @@ namespace Semmle.Autobuild.Shared
Argument("/t:restore").
QuoteArgument(projectOrSolution.FullPath);
if (nugetDownloaded)
if (builder.Actions.IsRunningOnAppleSilicon())
{
// On Apple Silicon, only try package restore with `dotnet msbuild /t:restore`
ret &= BuildScript.Try(msbuildRestoreCommand.Script);
}
else if (nugetDownloaded)
{
ret &= BuildScript.Try(nugetRestore | msbuildRestoreCommand.Script);
}

View File

@@ -23,6 +23,8 @@ namespace Semmle.Autobuild.Shared
public Version ToolsVersion { get; private set; }
public string? TargetFramework { get; private set; }
private readonly Lazy<List<Project<TAutobuildOptions>>> includedProjectsLazy;
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjectsLazy.Value;
@@ -51,7 +53,8 @@ namespace Semmle.Autobuild.Shared
{
if (root.HasAttribute("Sdk"))
{
DotNetProject = true;
this.DotNetProject = true;
this.TargetFramework = root.SelectSingleNode("//Project/PropertyGroup/TargetFramework/text()")?.Value;
return;
}
@@ -72,11 +75,12 @@ namespace Semmle.Autobuild.Shared
includedProjectsLazy = new Lazy<List<Project<TAutobuildOptions>>>(() =>
{
var mgr = new XmlNamespaceManager(projFile.NameTable);
mgr.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
var ret = new List<Project<TAutobuildOptions>>();
// The documentation on `.proj` files is very limited, but it appears that both
// `<ProjectFile Include="X"/>` and `<ProjectFiles Include="X"/>` is valid
var mgr = new XmlNamespaceManager(projFile.NameTable);
mgr.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
var projectFileIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFile/@Include", mgr)
?.OfType<XmlNode>() ?? Array.Empty<XmlNode>();
var projectFilesIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFiles/@Include", mgr)

View File

@@ -61,6 +61,12 @@ namespace Semmle.Autobuild.Shared
{
try
{
// SolutionFile.Parse won't throw a FileNotFoundException if it is given a Windows path on a non-Windows platform
if (!builder.Actions.FileExists(FullPath))
{
throw new FileNotFoundException(FullPath);
}
solution = SolutionFile.Parse(FullPath);
}
catch (Exception ex) when (ex is InvalidProjectFileException || ex is FileNotFoundException)

View File

@@ -89,8 +89,10 @@ namespace Semmle.Extraction.CSharp.Populators
SyntaxKind.ModuleKeyword => Entities.AttributeKind.Module,
_ => throw new InternalError(node, "Unhandled global target")
};
foreach (var attribute in node.Attributes)
var attributes = node.Attributes;
for (var i = 0; i < attributes.Count; i++)
{
var attribute = attributes[i];
if (attributeLookup.Value(attribute) is AttributeData attributeData)
{
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly, kind);

View File

@@ -1,24 +1,6 @@
import os
from create_database_utils import *
from diagnostics_test_utils import *
def is_running_on_apple_silicon():
arch = subprocess.Popen(['sysctl', 'machdep.cpu.brand_string'], stdout=subprocess.PIPE)
output, errors = arch.communicate()
if b'apple' in output.lower():
return True
return False
# if on ARM runners, remove Mono from the path, so we're using
# dotnet restore instead of nuget.exe restore - on ARM machines
# we run dotnet msbuild (instead of the mono-provided msbuild.exe)
# so we need to match the restore command, too.
platform_name = sys.platform.lower()
if platform_name.startswith("darwin") and is_running_on_apple_silicon():
os.environ["PATH"] = os.environ["PATH"].replace("/Library/Frameworks/Mono.framework/Versions/Current/Commands:", "")
# force CodeQL to use MSBuild by setting `LGTM_INDEX_MSBUILD_TARGET`
run_codeql_database_create([], db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' })
check_diagnostics()

View File

@@ -0,0 +1 @@
Skipping the test on the ARM runners, as we're running into trouble with Mono and nuget.

View File

@@ -0,0 +1,2 @@
| standalone.cs:3:12:3:29 | [assembly: Attribute1(...)] |
| standalone.cs:9:2:9:11 | [Attribute1(...)] |

View File

@@ -0,0 +1,5 @@
import csharp
from Attribute a
where a.getType().getName() = "Attribute1Attribute"
select a

View File

@@ -0,0 +1 @@
semmle-extractor-options: --standalone

View File

@@ -0,0 +1,12 @@
using System;
[assembly: global::Attribute1]
class Attribute1Attribute : Attribute
{
}
[Attribute1]
class A
{
}

View File

@@ -42,14 +42,47 @@ Downloading a database from GitHub
.. include:: ../reusables/download-github-database.rst
.. _filtering-databases-and-queries-by-language:
Filtering databases and queries by language
-------------------------------------------
Optionally, to see databases containing a specific language and queries written for that language, you can apply a language filter using the language selector.
#. To see available language filters, in the sidebar, click the **Language** title bar.
#. Hover over the language filter you would like to apply, then click **Select**.
.. image:: ../images/codeql-for-visual-studio-code/choose-language-filter.png
:width: 350
:alt: Screenshot of the language selector. The "Select" button for a language filter is outlined in dark orange.
Creating a custom query
------------------------
You can generate a query template for a specific language from the queries panel, then write your own code to quickly create a custom query.
#. Optionally, to create a custom query in an existing directory, in the sidebar, click the **Queries** title bar to expand the queries panel, then select the desired directory.
#. In the sidebar, hover over the **Queries** title bar, then click the **Create query** icon.
.. image:: ../images/codeql-for-visual-studio-code/create-query-icon.png
:width: 350
:alt: Screenshot of the queries panel. The "Create query" icon is outlined in dark orange.
#. In the Command Palette, select the target language for your query. If you've chosen not to create your custom query in an existing directory, selecting a language will autogenerate a directory labeled ``codeql-custom-queries-<language>``, where ``<language>`` is the name of the selected language. A query template labeled ``example.ql`` will then be added to the existing or autogenerated directory.
#. In the template, write your custom query, then save the file. Once your query is finished, you can run it from the queries panel.
Running a query
------------------------
The `CodeQL repository <https://github.com/github/codeql>`__ on GitHub contains lots of example queries.
If you have that folder (or a different CodeQL pack) available in your workspace, you can access existing queries under ``<language>/ql/src/<category>``, for example ``java/ql/src/Likely Bugs``.
You can access any existing queries in your workspace through the queries panel.
#. Open a query (``.ql``) file. It is displayed in the editor, with IntelliSense features such as syntax highlighting and autocomplete suggestions.
#. Right-click in the query window and select **CodeQL: Run Query on Selected Database**. (Alternatively, run the command from the Command Palette.)
#. In the sidebar, to expand the queries panel, click the **Queries** title bar.
#. To run a query against the selected database, hover over the desired query, then click the **Run local query** icon.
.. image:: ../images/codeql-for-visual-studio-code/run-local-query-icon.png
:width: 350
:alt: Screenshot of the mouse pointer hovering over a query in the queries panel. The "Run local query" icon is outlined in dark orange.
The CodeQL extension runs the query on the current database and reports progress in the bottom right corner of the application.
When the results are ready, they're displayed in the Results view.
@@ -61,6 +94,23 @@ For more information, see ":doc:`Troubleshooting CodeQL for Visual Studio Code <
Running multiple queries
--------------------------
You can quickly run multiple queries against the database you've selected using the queries panel or a single command.
Running all queries in a directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can easily run every query in a directory using the queries panel.
#. In the sidebar, to expand the queries panel, click the **Queries** title bar.
#. Hover over the desired directory of queries, then click the **Run local queries** icon.
.. image:: ../images/codeql-for-visual-studio-code/run-local-queries-icon.png
:width: 350
:alt: Screenshot of the mouse pointer hovering over a directory of queries in the queries panel. The "Run local queries" icon is outlined in dark orange.
Running a selection of queries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can run multiple queries with a single command.
#. Go to the File Explorer.
@@ -122,6 +172,7 @@ To see the queries that you have run in the current session, open the Query Hist
The Query History contains information including the date and time when the query was run, the name of the query, the database on which it was run, and how long it took to run the query.
To customize the information that is displayed, right-click an entry and select **Rename**.
You can also filter the Query History view by language using the language selector. For more information, see ":ref:`Filtering databases and queries by language <filtering-databases-and-queries-by-language>`."
Click an entry to display the corresponding results in the Query Results view, and double-click
to display the query itself in the editor (or right-click and select **View Query**).

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -49,7 +49,7 @@ The following properties are supported by all query files:
| | | ``warning`` | |
| | | ``recommendation`` | |
+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``@security-severity``| ``<score>`` | Defines the level of severity, between 0.0 and 10.0, for queries with ``@tags security``. For more information about calculating ``@security-severity``, see the `GitHub changelog <https://github.blog/changelog/2021-07-19-codeql-code-scanning-new-severity-levels-for-security-alerts/>`__. |
| ``@security-severity``| ``<score>`` | Defines the level of severity, between 0.0 and 10.0, for queries with ``@tags security``. For more information about calculating ``@security-severity``, see the `GitHub changelog <https://gh.io/2021-07-19-codeql-security-severity>`__. |
+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Example

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* A bug has been fixed that meant that value flow through an array was not tracked correctly in some circumstances. Taint flow was tracked correctly.

View File

@@ -724,16 +724,19 @@ class GenericTypeInstantiationExpr extends Expr {
* ```go
* a[1:3]
* a[1:3:5]
* a[1:]
* a[:3]
* a[:]
* ```
*/
class SliceExpr extends @sliceexpr, Expr {
/** Gets the base of this slice expression. */
Expr getBase() { result = this.getChildExpr(0) }
/** Gets the lower bound of this slice expression. */
/** Gets the lower bound of this slice expression, if any. */
Expr getLow() { result = this.getChildExpr(1) }
/** Gets the upper bound of this slice expression. */
/** Gets the upper bound of this slice expression, if any. */
Expr getHigh() { result = this.getChildExpr(2) }
/** Gets the maximum of this slice expression, if any. */

View File

@@ -21,7 +21,7 @@ predicate containerStoreStep(Node node1, Node node2, Content c) {
node2.getType() instanceof SliceType
) and
(
exists(Write w | w.writesElement(node2, _, node1))
exists(Write w | w.writesElement(node2.(PostUpdateNode).getPreUpdateNode(), _, node1))
or
node1 = node2.(ImplicitVarargsSlice).getCallNode().getAnImplicitVarargsArgument()
)

View File

@@ -21,5 +21,5 @@ func main() {
// Compare with the standard dataflow support for arrays
var b [4]string
b[0] = source()
sink(b[0]) // $ hasTaintFlow="index expression"
sink(b[0]) // $ hasValueFlow="index expression"
}

View File

@@ -47,6 +47,7 @@ edges
| test.go:246:15:246:36 | call to GetString | test.go:249:21:249:29 | untrusted |
| test.go:259:23:259:44 | call to GetCookie | test.go:259:16:259:45 | type conversion |
| test.go:270:62:270:83 | call to GetCookie | test.go:270:55:270:84 | type conversion |
| test.go:275:2:275:40 | ... := ...[0] | test.go:278:21:278:28 | index expression |
| test.go:275:2:275:40 | ... := ...[0] | test.go:283:44:283:60 | selection of Filename |
| test.go:275:2:275:40 | ... := ...[0] | test.go:284:38:284:49 | genericFiles |
| test.go:275:2:275:40 | ... := ...[0] | test.go:285:37:285:48 | genericFiles |
@@ -61,6 +62,8 @@ edges
| test.go:275:2:275:40 | ... := ...[0] | test.go:301:39:301:50 | genericFiles |
| test.go:275:2:275:40 | ... := ...[0] | test.go:302:40:302:51 | genericFiles |
| test.go:275:2:275:40 | ... := ...[0] | test.go:303:39:303:50 | genericFiles |
| test.go:276:2:276:13 | definition of genericFiles [array] | test.go:297:51:297:62 | genericFiles [array] |
| test.go:278:21:278:28 | index expression | test.go:276:2:276:13 | definition of genericFiles [array] |
| test.go:283:44:283:60 | selection of Filename | test.go:283:21:283:61 | call to GetDisplayString |
| test.go:284:21:284:53 | call to SliceChunk | test.go:284:21:284:92 | selection of Filename |
| test.go:284:38:284:49 | genericFiles | test.go:284:21:284:53 | call to SliceChunk |
@@ -77,6 +80,7 @@ edges
| test.go:296:21:296:61 | call to SliceMerge | test.go:296:21:296:97 | selection of Filename |
| test.go:296:49:296:60 | genericFiles | test.go:296:21:296:61 | call to SliceMerge |
| test.go:297:21:297:66 | call to SlicePad | test.go:297:21:297:102 | selection of Filename |
| test.go:297:51:297:62 | genericFiles [array] | test.go:297:51:297:65 | index expression |
| test.go:297:51:297:65 | index expression | test.go:297:21:297:66 | call to SlicePad |
| test.go:298:21:298:66 | call to SlicePad | test.go:298:21:298:102 | selection of Filename |
| test.go:298:36:298:47 | genericFiles | test.go:298:21:298:66 | call to SlicePad |
@@ -177,6 +181,8 @@ nodes
| test.go:270:55:270:84 | type conversion | semmle.label | type conversion |
| test.go:270:62:270:83 | call to GetCookie | semmle.label | call to GetCookie |
| test.go:275:2:275:40 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:276:2:276:13 | definition of genericFiles [array] | semmle.label | definition of genericFiles [array] |
| test.go:278:21:278:28 | index expression | semmle.label | index expression |
| test.go:283:21:283:61 | call to GetDisplayString | semmle.label | call to GetDisplayString |
| test.go:283:44:283:60 | selection of Filename | semmle.label | selection of Filename |
| test.go:284:21:284:53 | call to SliceChunk | semmle.label | call to SliceChunk |
@@ -202,6 +208,7 @@ nodes
| test.go:296:49:296:60 | genericFiles | semmle.label | genericFiles |
| test.go:297:21:297:66 | call to SlicePad | semmle.label | call to SlicePad |
| test.go:297:21:297:102 | selection of Filename | semmle.label | selection of Filename |
| test.go:297:51:297:62 | genericFiles [array] | semmle.label | genericFiles [array] |
| test.go:297:51:297:65 | index expression | semmle.label | index expression |
| test.go:298:21:298:66 | call to SlicePad | semmle.label | call to SlicePad |
| test.go:298:21:298:102 | selection of Filename | semmle.label | selection of Filename |

View File

@@ -1,6 +1,9 @@
#!/bin/sh
set -e
# Before running this, make sure there is an SSO-enabled token with package:write
# permissions to codeql supplied via the GITHUB_TOKEN environment variable
AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")"
WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.."
GRPS="automodel,-test"

View File

@@ -30,7 +30,9 @@ newtype TApplicationModeEndpoint =
arg.asExpr() = argExpr and call = argExpr.getCall() and not argExpr.isVararg()
)
} or
TInstanceArgument(Call call, DataFlow::Node arg) { arg = DataFlow::getInstanceArgument(call) } or
TInstanceArgument(Call call, DataFlow::Node arg) {
arg = DataFlow::getInstanceArgument(call) and not call instanceof ConstructorCall
} or
TImplicitVarargsArray(Call call, DataFlow::Node arg, int idx) {
exists(Argument argExpr |
arg.asExpr() = argExpr and

View File

@@ -25,7 +25,7 @@ newtype JavaRelatedLocationType =
newtype TFrameworkModeEndpoint =
TExplicitParameter(Parameter p) or
TQualifier(Callable c) or
TQualifier(Callable c) { not c instanceof Constructor } or
TReturnValue(Callable c) or
TOverridableParameter(Method m, Parameter p) {
p.getCallable() = m and

View File

@@ -1,3 +1,3 @@
## 0.0.7
No user-facing changes.
Support for extracting source candidates.

View File

@@ -1,13 +1,13 @@
| PluginImpl.java:5:27:5:37 | name | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:27:5:37 | name | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| PluginImpl.java:5:40:5:51 | value | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:40:5:51 | value | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[1]:1:1:1:1 | Parameter[1] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:18:3:18:11 | reference | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:18:3:18:24 | set(...) | CallContext | Test.java:18:3:18:11 | reference | MethodDoc | Test.java:18:3:18:11 | reference | ClassDoc | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:23:3:23:10 | supplier | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:23:3:23:16 | get(...) | CallContext | Test.java:23:3:23:10 | supplier | MethodDoc | Test.java:23:3:23:10 | supplier | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:23:3:23:16 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:23:3:23:16 | get(...) | CallContext | Test.java:23:3:23:16 | get(...) | MethodDoc | Test.java:23:3:23:16 | get(...) | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:27:3:31:3 | copy(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:27:3:31:3 | copy(...) | CallContext | Test.java:27:3:31:3 | copy(...) | MethodDoc | Test.java:27:3:31:3 | copy(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:35:10:37:3 | newInputStream(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:35:10:37:3 | newInputStream(...) | CallContext | Test.java:35:10:37:3 | newInputStream(...) | MethodDoc | Test.java:35:10:37:3 | newInputStream(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:36:4:36:11 | openPath | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:35:10:37:3 | newInputStream(...) | CallContext | Test.java:36:4:36:11 | openPath | MethodDoc | Test.java:36:4:36:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:42:4:42:22 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:42:4:42:22 | get(...) | CallContext | Test.java:42:4:42:22 | get(...) | MethodDoc | Test.java:42:4:42:22 | get(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Paths:1:1:1:1 | Paths | type | file://false:1:1:1:1 | false | subtypes | file://get:1:1:1:1 | get | name | file://(String,String[]):1:1:1:1 | (String,String[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:53:3:58:3 | walk(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:53:3:58:3 | walk(...) | CallContext | Test.java:53:3:58:3 | walk(...) | MethodDoc | Test.java:53:3:58:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:55:4:55:4 | o | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:53:3:58:3 | walk(...) | CallContext | Test.java:53:3:58:3 | walk(...) | MethodDoc | Test.java:53:3:58:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:62:3:62:3 | c | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:62:3:62:20 | getInputStream(...) | CallContext | Test.java:62:3:62:3 | c | MethodDoc | Test.java:62:3:62:3 | c | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:67:30:67:47 | writer | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:67:30:67:47 | writer | CallContext | Test.java:67:30:67:47 | writer | MethodDoc | Test.java:67:30:67:47 | writer | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Throwable:1:1:1:1 | Throwable | type | file://true:1:1:1:1 | true | subtypes | file://printStackTrace:1:1:1:1 | printStackTrace | name | file://(PrintWriter):1:1:1:1 | (PrintWriter) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:19:3:19:11 | reference | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:19:3:19:24 | set(...) | CallContext | Test.java:19:3:19:11 | reference | MethodDoc | Test.java:19:3:19:11 | reference | ClassDoc | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:24:3:24:10 | supplier | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:10 | supplier | MethodDoc | Test.java:24:3:24:10 | supplier | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:24:3:24:16 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:16 | get(...) | MethodDoc | Test.java:24:3:24:16 | get(...) | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:28:3:32:3 | copy(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:28:3:32:3 | copy(...) | MethodDoc | Test.java:28:3:32:3 | copy(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:36:10:38:3 | newInputStream(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:36:10:38:3 | newInputStream(...) | MethodDoc | Test.java:36:10:38:3 | newInputStream(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:37:4:37:11 | openPath | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:43:4:43:22 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:43:4:43:22 | get(...) | CallContext | Test.java:43:4:43:22 | get(...) | MethodDoc | Test.java:43:4:43:22 | get(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Paths:1:1:1:1 | Paths | type | file://false:1:1:1:1 | false | subtypes | file://get:1:1:1:1 | get | name | file://(String,String[]):1:1:1:1 | (String,String[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:54:3:59:3 | walk(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:56:4:56:4 | o | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:63:3:63:3 | c | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:3 | c | MethodDoc | Test.java:63:3:63:3 | c | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:68:30:68:47 | writer | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:68:30:68:47 | writer | CallContext | Test.java:68:30:68:47 | writer | MethodDoc | Test.java:68:30:68:47 | writer | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Throwable:1:1:1:1 | Throwable | type | file://true:1:1:1:1 | true | subtypes | file://printStackTrace:1:1:1:1 | printStackTrace | name | file://(PrintWriter):1:1:1:1 | (PrintWriter) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |

View File

@@ -1,4 +1,3 @@
| Test.java:47:10:49:3 | compareTo(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:47:10:49:3 | compareTo(...) | CallContext | Test.java:47:10:49:3 | compareTo(...) | MethodDoc | Test.java:47:10:49:3 | compareTo(...) | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:48:4:48:5 | f2 | known non-sink\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:47:10:49:3 | compareTo(...) | CallContext | Test.java:48:4:48:5 | f2 | MethodDoc | Test.java:48:4:48:5 | f2 | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:54:4:54:4 | p | taint step\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:53:3:58:3 | walk(...) | CallContext | Test.java:54:4:54:4 | p | MethodDoc | Test.java:54:4:54:4 | p | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:66:7:66:18 | this <constr(this)> | exception\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:66:7:66:18 | super(...) | CallContext | Test.java:66:7:66:18 | super(...) | MethodDoc | Test.java:66:7:66:18 | super(...) | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Exception:1:1:1:1 | Exception | type | file://true:1:1:1:1 | true | subtypes | file://Exception:1:1:1:1 | Exception | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:48:10:50:3 | compareTo(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:48:10:50:3 | compareTo(...) | MethodDoc | Test.java:48:10:50:3 | compareTo(...) | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:49:4:49:5 | f2 | known non-sink\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:49:4:49:5 | f2 | MethodDoc | Test.java:49:4:49:5 | f2 | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:55:4:55:4 | p | taint step\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:55:4:55:4 | p | MethodDoc | Test.java:55:4:55:4 | p | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |

View File

@@ -1,4 +1,4 @@
| Test.java:28:4:28:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:27:3:31:3 | copy(...) | CallContext | Test.java:28:4:28:9 | source | MethodDoc | Test.java:28:4:28:9 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:29:4:29:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:27:3:31:3 | copy(...) | CallContext | Test.java:29:4:29:9 | target | MethodDoc | Test.java:29:4:29:9 | target | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:36:4:36:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:35:10:37:3 | newInputStream(...) | CallContext | Test.java:36:4:36:11 | openPath | MethodDoc | Test.java:36:4:36:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:62:3:62:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:62:3:62:20 | getInputStream(...) | CallContext | Test.java:62:3:62:20 | getInputStream(...) | MethodDoc | Test.java:62:3:62:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| Test.java:29:4:29:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:29:4:29:9 | source | MethodDoc | Test.java:29:4:29:9 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:30:4:30:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:30:4:30:9 | target | MethodDoc | Test.java:30:4:30:9 | target | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:37:4:37:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| Test.java:63:3:63:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:20 | getInputStream(...) | MethodDoc | Test.java:63:3:63:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |

View File

@@ -11,6 +11,7 @@ import java.util.function.Supplier;
import java.io.File;
import java.nio.file.FileVisitOption;
import java.net.URLConnection;
import java.util.concurrent.FutureTask;
class Test {
public static void main(String[] args) throws Exception {
@@ -67,4 +68,15 @@ class OverrideTest extends Exception {
public void printStackTrace(PrintWriter writer) { // writer is a source candidate because it overrides an existing method
return;
}
}
class TaskUtils {
public FutureTask getTask() {
FutureTask ft = new FutureTask(() -> {
// ^-- no sink candidate for the `this` qualifier of a constructor
return 42;
});
return ft;
}
}

View File

@@ -10,6 +10,8 @@
| com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | MethodDoc | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | MethodDoc | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| com/github/codeql/test/PublicClass.java:22:22:22:33 | input | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | MethodDoc | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://input:1:1:1:1 | input | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |

View File

@@ -18,4 +18,8 @@ public class PublicClass {
void packagePrivateStuff(String arg) {
System.out.println(arg);
}
public PublicClass(Object input) {
// the `this` qualifier is not a candidate
}
}

View File

@@ -2,23 +2,11 @@ public void sendUserFile(Socket sock, String user) {
BufferedReader filenameReader = new BufferedReader(
new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
// BAD: read from a file using a path controlled by the user
BufferedReader fileReader = new BufferedReader(
new FileReader("/home/" + user + "/" + filename));
// BAD: read from a file without checking its path
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
String fileLine = fileReader.readLine();
while(fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileFixed(Socket sock, String user) {
// ...
// GOOD: remove all dots and directory delimiters from the filename before using
String filename = filenameReader.readLine().replaceAll("\\.", "").replaceAll("/", "");
BufferedReader fileReader = new BufferedReader(
new FileReader("/home/" + user + "/" + filename));
// ...
}

View File

@@ -8,32 +8,44 @@ can result in sensitive information being revealed or deleted, or an attacker be
behavior by modifying unexpected files.</p>
<p>Paths that are naively constructed from data controlled by a user may contain unexpected special characters,
such as "..". Such a path may potentially point to any directory on the file system.</p>
such as "..". Such a path may potentially point anywhere on the file system.</p>
</overview>
<recommendation>
<p>Validate user input before using it to construct a file path. Ideally, follow these rules:</p>
<p>Validate user input before using it to construct a file path.</p>
<ul>
<li>Do not allow more than a single "." character.</li>
<li>Do not allow directory separators such as "/" or "\" (depending on the file system).</li>
<li>Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to
".../...//" the resulting string would still be "../".</li>
<li>Ideally use a whitelist of known good patterns.</li>
</ul>
<p>The choice of validation depends on whether you want to allow the user to specify complex paths with
multiple components that may span multiple folders, or only simple filenames without a path component.</p>
<p>In the former case, a common strategy is to make sure that the constructed file path is contained within
a safe root folder, for example by checking that the path starts with the root folder. Additionally,
you need to ensure that the path does not contain any ".." components, since otherwise
even a path that starts with the root folder could be used to access files outside the root folder.</p>
<p>In the latter case, if you want to ensure that the user input is interpreted as a simple filename without
a path component, you can remove all path separators ("/" or "\") and all ".." sequences from the input
before using it to construct a file path. Note that it is <i>not</i> sufficient to only remove "../" sequences:
for example, applying this filter to ".../...//" would still result in the string "../".</p>
<p>Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that
the user input matches one of these patterns.</p>
</recommendation>
<example>
<p>In this example, a file name is read from a <code>java.net.Socket</code> and then used to access a file in the
user's home directory and send it back over the socket. However, a malicious user could enter a file name which contains special
characters. For example, the string "../../etc/passwd" will result in the code reading the file located at
"/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user,
giving them access to all the system's passwords.</p>
<p>In this example, a file name is read from a <code>java.net.Socket</code> and then used to access a file
and send it back over the socket. However, a malicious user could enter a file name anywhere on the file system,
such as "/etc/passwd".</p>
<sample src="TaintedPath.java" />
<p>Simply checking that the path is under a trusted location (such as a known public folder) is not enough,
however, since the path could contain relative components such as "..". To fix this, check that it does
not contain ".." and starts with the public folder.</p>
<sample src="TaintedPathGood.java" />
</example>
<references>

View File

@@ -0,0 +1,14 @@
public void sendUserFileGood(Socket sock, String user) {
BufferedReader filenameReader = new BufferedReader(
new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
// GOOD: ensure that the file is in a designated folder in the user's home directory
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
String fileLine = fileReader.readLine();
while(fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
}

View File

@@ -1,4 +1,9 @@
edges
| TaintedPath.java:11:38:11:110 | new BufferedReader(...) : BufferedReader | TaintedPath.java:12:24:12:37 | filenameReader : BufferedReader |
| TaintedPath.java:11:57:11:109 | new InputStreamReader(...) : InputStreamReader | TaintedPath.java:11:38:11:110 | new BufferedReader(...) : BufferedReader |
| TaintedPath.java:11:79:11:99 | getInputStream(...) : InputStream | TaintedPath.java:11:57:11:109 | new InputStreamReader(...) : InputStreamReader |
| TaintedPath.java:12:24:12:37 | filenameReader : BufferedReader | TaintedPath.java:12:24:12:48 | readLine(...) : String |
| TaintedPath.java:12:24:12:48 | readLine(...) : String | TaintedPath.java:14:68:14:75 | filename |
| Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp |
| Test.java:19:18:19:38 | getHostName(...) : String | Test.java:27:21:27:24 | temp |
| Test.java:19:18:19:38 | getHostName(...) : String | Test.java:30:44:30:47 | temp |
@@ -184,6 +189,12 @@ edges
| mad/Test.java:221:26:221:33 | source(...) : String | mad/Test.java:221:19:221:33 | (...)... |
| mad/Test.java:226:29:226:36 | source(...) : String | mad/Test.java:226:20:226:36 | (...)... |
nodes
| TaintedPath.java:11:38:11:110 | new BufferedReader(...) : BufferedReader | semmle.label | new BufferedReader(...) : BufferedReader |
| TaintedPath.java:11:57:11:109 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
| TaintedPath.java:11:79:11:99 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TaintedPath.java:12:24:12:37 | filenameReader : BufferedReader | semmle.label | filenameReader : BufferedReader |
| TaintedPath.java:12:24:12:48 | readLine(...) : String | semmle.label | readLine(...) : String |
| TaintedPath.java:14:68:14:75 | filename | semmle.label | filename |
| Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| Test.java:24:20:24:23 | temp | semmle.label | temp |
| Test.java:27:21:27:24 | temp | semmle.label | temp |
@@ -375,6 +386,7 @@ nodes
| mad/Test.java:226:29:226:36 | source(...) : String | semmle.label | source(...) : String |
subpaths
#select
| TaintedPath.java:14:53:14:76 | new FileReader(...) | TaintedPath.java:11:79:11:99 | getInputStream(...) : InputStream | TaintedPath.java:14:68:14:75 | filename | This path depends on a $@. | TaintedPath.java:11:79:11:99 | getInputStream(...) | user-provided value |
| 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 |
| Test.java:27:11:27:25 | get(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:27:21:27:24 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
| Test.java:30:11:30:48 | getPath(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:30:44:30:47 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |

View File

@@ -0,0 +1,35 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
public class TaintedPath {
public void sendUserFile(Socket sock, String user) throws IOException {
BufferedReader filenameReader = new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
// BAD: read from a file without checking its path
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
String fileLine = fileReader.readLine();
while(fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileGood(Socket sock, String user) throws IOException {
BufferedReader filenameReader = new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
// GOOD: ensure that the file is in a designated folder in the user's home directory
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
String fileLine = fileReader.readLine();
while(fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
}
}

View File

@@ -101,4 +101,12 @@ class Test {
new File(new URI(null, null, null, 0, t, null, null));
}
void doGet6(String root, InetAddress address)
throws IOException{
String temp = address.getHostName();
// GOOD: Use `contains` and `startsWith` to check if the path is safe
if (!temp.contains("..") && temp.startsWith(root + "/")) {
File file = new File(temp);
}
}
}

View File

@@ -4,7 +4,7 @@
* a cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity error
* @security-severity 6.1
* @security-severity 7.8
* @precision high
* @id js/reflected-xss
* @tags security

View File

@@ -4,7 +4,7 @@
* a stored cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity error
* @security-severity 6.1
* @security-severity 7.8
* @precision high
* @id js/stored-xss
* @tags security

View File

@@ -4,7 +4,7 @@
* a cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity error
* @security-severity 6.1
* @security-severity 7.8
* @precision high
* @id js/xss
* @tags security

View File

@@ -4,7 +4,7 @@
* insertion of forged log entries by a malicious user.
* @kind path-problem
* @problem.severity error
* @security-severity 7.8
* @security-severity 6.1
* @precision medium
* @id js/log-injection
* @tags security

View File

@@ -4,6 +4,7 @@
* @description The total number of lines of JavaScript or TypeScript code across all files checked into the repository, except in `node_modules`. This is a useful metric of the size of a database. For all files that were seen during extraction, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
* telemetry
*/
import javascript

View File

@@ -0,0 +1,6 @@
---
category: queryMetadata
---
* Lower the severity of log-injection to medium.
* Increase the severity of XSS to high.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added basic flow for attributes defined on classes, when the attribute lookup is on a direct reference to that class (so not instance, cls parameter, or self parameter). Example: class definition `class Foo: my_tuples = (dangerous, safe)` and usage `SINK(Foo.my_tuples[0])`.

View File

@@ -5,13 +5,18 @@
// If you add modeling of a new framework/library, remember to add it to the docs in
// `docs/codeql/reusables/supported-frameworks.rst`
private import semmle.python.frameworks.Aioch
private import semmle.python.frameworks.Aiofile
private import semmle.python.frameworks.Aiofiles
private import semmle.python.frameworks.Aiohttp
private import semmle.python.frameworks.Aiomysql
private import semmle.python.frameworks.Aiopg
private import semmle.python.frameworks.Aiosqlite
private import semmle.python.frameworks.Anyio
private import semmle.python.frameworks.Asyncpg
private import semmle.python.frameworks.Baize
private import semmle.python.frameworks.BSon
private import semmle.python.frameworks.CassandraDriver
private import semmle.python.frameworks.Cherrypy
private import semmle.python.frameworks.ClickhouseDriver
private import semmle.python.frameworks.Cryptodome
private import semmle.python.frameworks.Cryptography
@@ -54,6 +59,7 @@ private import semmle.python.frameworks.Requests
private import semmle.python.frameworks.RestFramework
private import semmle.python.frameworks.Rsa
private import semmle.python.frameworks.RuamelYaml
private import semmle.python.frameworks.Sanic
private import semmle.python.frameworks.ServerLess
private import semmle.python.frameworks.Setuptools
private import semmle.python.frameworks.Simplejson

View File

@@ -846,10 +846,27 @@ predicate comprehensionStoreStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
* ```
* data flows from `x` to the attribute `foo` of (the post-update node for) `obj`.
*/
predicate attributeStoreStep(Node nodeFrom, AttributeContent c, PostUpdateNode nodeTo) {
exists(AttrWrite write |
write.accesses(nodeTo.getPreUpdateNode(), c.getAttribute()) and
nodeFrom = write.getValue()
predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
exists(Node object |
// Normally we target a PostUpdateNode. However, for class definitions the class
// is only constructed after evaluating its' entire scope, so in terms of python
// evaluations there is no post or pre update nodes, just one node for the class
// expression. Therefore we target the class expression directly.
//
// Note: Due to the way we handle decorators, using a class decorator will result in
// there being a post-update node for the class (argument to the decorator). We do
// not want to differentiate between these two cases, so still target the class
// expression directly.
object = nodeTo.(PostUpdateNode).getPreUpdateNode() and
not object.asExpr() instanceof ClassExpr
or
object = nodeTo and
object.asExpr() instanceof ClassExpr
|
exists(AttrWrite write |
write.accesses(object, c.getAttribute()) and
nodeFrom = write.getValue()
)
)
}

View File

@@ -0,0 +1,42 @@
/**
* Provides classes modeling security-relevant aspects of the `aiofile` PyPI package.
*
* See https://pypi.org/project/aiofile.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
/**
* Provides models for the `aiofile` PyPI package.
*
* See https://pypi.org/project/aiofile.
*/
private module Aiofile {
/**
* A call to the `async_open` function or `AIOFile` constructor from `aiofile` as a sink for Filesystem access.
*/
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
string methodName;
FileResponseCall() {
this = API::moduleImport("aiofile").getMember("async_open").getACall() and
methodName = "async_open"
or
this = API::moduleImport("aiofile").getMember("AIOFile").getACall() and
methodName = "AIOFile"
}
override DataFlow::Node getAPathArgument() {
result = this.getParameter(0, "file_specifier").asSink() and
methodName = "async_open"
or
result = this.getParameter(0, "filename").asSink() and
methodName = "AIOFile"
}
}
}

View File

@@ -0,0 +1,28 @@
/**
* Provides classes modeling security-relevant aspects of the `aiofiles` PyPI package.
*
* See https://pypi.org/project/aiofiles.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
/**
* Provides models for the `aiofiles` PyPI package.
*
* See https://pypi.org/project/aiofiles.
*/
private module Aiofiles {
/**
* A call to the `open` function from `aiofiles` as a sink for Filesystem access.
*/
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
FileResponseCall() { this = API::moduleImport("aiofiles").getMember("open").getACall() }
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() }
}
}

View File

@@ -0,0 +1,54 @@
/**
* Provides classes modeling security-relevant aspects of the `anyio` PyPI package.
*
* See https://pypi.org/project/anyio.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
/**
* Provides models for the `anyio` PyPI package.
*
* See https://pypi.org/project/anyio.
*/
private module Anyio {
/**
* A call to the `from_path` function from `FileReadStream` or `FileWriteStream` constructors of `anyio.streams.file` as a sink for Filesystem access.
*/
class FileStreamCall extends FileSystemAccess::Range, API::CallNode {
FileStreamCall() {
this =
API::moduleImport("anyio")
.getMember("streams")
.getMember("file")
.getMember(["FileReadStream", "FileWriteStream"])
.getMember("from_path")
.getACall()
}
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() }
}
/**
* A call to the `Path` constructor from `anyio` as a sink for Filesystem access.
*/
class PathCall extends FileSystemAccess::Range, API::CallNode {
PathCall() { this = API::moduleImport("anyio").getMember("Path").getACall() }
override DataFlow::Node getAPathArgument() { result = this.getParameter(0).asSink() }
}
/**
* A call to the `open_file` function from `anyio` as a sink for Filesystem access.
*/
class OpenFileCall extends FileSystemAccess::Range, API::CallNode {
OpenFileCall() { this = API::moduleImport("anyio").getMember("open_file").getACall() }
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() }
}
}

View File

@@ -0,0 +1,35 @@
/**
* Provides classes modeling security-relevant aspects of the `baize` PyPI package.
*
* See https://pypi.org/project/baize.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
private import semmle.python.frameworks.Stdlib
/**
* Provides models for `baize` PyPI package.
*
* See https://pypi.org/project/baize.
*/
module Baize {
/**
* A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access.
*
* it is not contained to Starlette source code but it is mentioned in documents as an alternative to Starlette FileResponse
*/
class BaizeFileResponseCall extends FileSystemAccess::Range, API::CallNode {
BaizeFileResponseCall() {
this = API::moduleImport("baize").getMember("asgi").getMember("FileResponse").getACall()
}
override DataFlow::Node getAPathArgument() {
result = this.getParameter(0, "filepath").asSink()
}
}
}

View File

@@ -0,0 +1,48 @@
/**
* Provides classes modeling security-relevant aspects of the `cherrypy` PyPI package.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
/**
* Provides models for the `cherrypy` PyPI package.
* See https://cherrypy.dev/.
*/
private module Cherrypy {
/**
* Holds for an instance of `cherrypy.lib.static`
*/
API::Node libStatic() {
result = API::moduleImport("cherrypy").getMember("lib").getMember("static")
}
/**
* A call to the `serve_file` or `serve_download`or `staticfile` functions of `cherrypy.lib.static` as a sink for Filesystem access.
*/
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
string funcName;
FileResponseCall() {
this = libStatic().getMember("staticfile").getACall() and
funcName = "staticfile"
or
this = libStatic().getMember("serve_file").getACall() and
funcName = "serve_file"
or
this = libStatic().getMember("serve_download").getACall() and
funcName = "serve_download"
}
override DataFlow::Node getAPathArgument() {
result = this.getParameter(0, "path").asSink() and funcName = ["serve_download", "serve_file"]
or
result = this.getParameter(0, "filename").asSink() and
funcName = "staticfile"
}
}
}

View File

@@ -0,0 +1,42 @@
/**
* Provides classes modeling security-relevant aspects of the `sanic` PyPI package.
* See https://sanic.dev/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
/**
* Provides models for the `sanic` PyPI package.
* See https://sanic.dev/.
*/
private module Sanic {
/**
* Provides models for Sanic applications (an instance of `sanic.Sanic`).
*/
module App {
/** Gets a reference to a Sanic application (an instance of `sanic.Sanic`). */
API::Node instance() { result = API::moduleImport("sanic").getMember("Sanic").getReturn() }
}
/**
* A call to the `file` or `file_stream` functions of `sanic.response` as a sink for Filesystem access.
*/
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
FileResponseCall() {
this =
API::moduleImport("sanic")
.getMember("response")
.getMember(["file", "file_stream"])
.getACall()
}
override DataFlow::Node getAPathArgument() {
result = this.getParameter(0, "location").asSink()
}
}
}

View File

@@ -163,4 +163,16 @@ module Starlette {
/** DEPRECATED: Alias for Url */
deprecated module URL = Url;
/**
* A call to the `starlette.responses.FileResponse` constructor as a sink for Filesystem access.
*/
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
FileResponseCall() {
this =
API::moduleImport("starlette").getMember("responses").getMember("FileResponse").getACall()
}
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() }
}
}

View File

@@ -1479,6 +1479,26 @@ private module StdlibPrivate {
}
}
/**
* A call to the `io.FileIO` constructor.
* See https://docs.python.org/3/library/io.html#io.FileIO
*/
private class FileIOCall extends FileSystemAccess::Range, API::CallNode {
FileIOCall() { this = API::moduleImport("io").getMember("FileIO").getACall() }
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() }
}
/**
* A call to the `io.open_code` function.
* See https://docs.python.org/3.11/library/io.html#io.open_code
*/
private class OpenCodeCall extends FileSystemAccess::Range, API::CallNode {
OpenCodeCall() { this = API::moduleImport("io").getMember("open_code").getACall() }
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() }
}
/** Gets a reference to an open file. */
private DataFlow::TypeTrackingNode openFile(DataFlow::TypeTracker t, FileSystemAccess openCall) {
t.start() and

View File

@@ -5,6 +5,7 @@
* database. This query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
* telemetry
* @id py/summary/lines-of-code
*/

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=3

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added modeling of more `FileSystemAccess` in packages `cherrypy`, `aiofile`, `aiofiles`, `anyio`, `sanic`, `starlette`, `baize`, and `io`. This will mainly affect the _Uncontrolled data used in path expression_ (`py/path-injection`) query.

View File

@@ -8,4 +8,4 @@
| 38 | ControlFlowNode for ExceptStmt | builtin-class AttributeError |
| 40 | ControlFlowNode for ExceptStmt | builtin-class IndexError |
| 42 | ControlFlowNode for ExceptStmt | builtin-class KeyError |
| 57 | ControlFlowNode for ExceptStmt | builtin-class IOError |
| 57 | ControlFlowNode for ExceptStmt | builtin-class IOError |

View File

@@ -12,4 +12,4 @@
| 35 | ControlFlowNode for Attribute | builtin-class AttributeError |
| 37 | ControlFlowNode for Raise | builtin-class Exception |
| 53 | ControlFlowNode for Attribute() | builtin-class IOError |
| 54 | ControlFlowNode for Attribute() | builtin-class IOError |
| 54 | ControlFlowNode for Attribute() | builtin-class IOError |

View File

@@ -3,4 +3,4 @@
| 36 | ControlFlowNode for a() |
| 51 | ControlFlowNode for open() |
| 56 | ControlFlowNode for Attribute() |
| 58 | ControlFlowNode for Attribute() |
| 58 | ControlFlowNode for Attribute() |

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=2 --max-import-depth=2 -r package

View File

@@ -7,4 +7,4 @@
| 36 | class DerivedFromBuiltin | pop |
| 36 | class DerivedFromBuiltin | remove |
| 36 | class DerivedFromBuiltin | reverse |
| 36 | class DerivedFromBuiltin | sort |
| 36 | class DerivedFromBuiltin | sort |

View File

@@ -12,4 +12,4 @@
| Module package.helper | 2 | ImportExpr | 0 | bottom | absolute | assistant |
| Module package.helper | 3 | ImportExpr | 0 | top | absolute | sys |
| Module package.helper | 10 | ImportExpr | 1 | bottom | relative | package |
| Module test_star | 1 | ImportExpr | -1 | bottom | absolute | test_package |
| Module test_star | 1 | ImportExpr | -1 | bottom | absolute | test_package |

View File

@@ -54,4 +54,4 @@
| Module test_star | p | str b'p' |
| Module test_star | q | str b'q' |
| Module test_star | r | str b'r' |
| Module test_star | sys | Module sys |
| Module test_star | sys | Module sys |

View File

@@ -39,4 +39,4 @@
| Module test_star | p |
| Module test_star | q |
| Module test_star | r |
| Module test_star | sys |
| Module test_star | sys |

View File

@@ -5,4 +5,4 @@
| Module test_package.module2 | test_package.module2 |
| Module test_package.module3 | test_package.module3 |
| Module test_package.module4 | test_package.module4 |
| Module test_star | test_star |
| Module test_star | test_star |

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