Compare commits

..

1446 Commits

Author SHA1 Message Date
Mathias Vorreiter Pedersen
b13123e66e Merge pull request #9128 from github/release-prep/2.9.2
Release preparation for version 2.9.2
2022-05-12 13:04:08 +01:00
Mathias Vorreiter Pedersen
46f237efcb Update ruby/ql/lib/change-notes/released/0.2.1.md 2022-05-12 11:47:26 +01:00
Mathias Vorreiter Pedersen
103c589c1d Update python/ql/lib/change-notes/released/0.3.0.md 2022-05-12 11:47:19 +01:00
Mathias Vorreiter Pedersen
7b8c3bdcf9 Update ruby/ql/lib/CHANGELOG.md 2022-05-12 11:47:13 +01:00
Mathias Vorreiter Pedersen
499878a44d Update python/ql/lib/CHANGELOG.md 2022-05-12 11:47:08 +01:00
Mathias Vorreiter Pedersen
f76d52407d Update java/ql/lib/change-notes/released/0.2.1.md 2022-05-12 11:47:01 +01:00
Mathias Vorreiter Pedersen
1143b48338 Update java/ql/lib/CHANGELOG.md 2022-05-12 11:46:53 +01:00
Mathias Vorreiter Pedersen
55ce069e30 Update java/ql/lib/change-notes/released/0.2.1.md 2022-05-12 11:43:55 +01:00
Mathias Vorreiter Pedersen
43265c4133 Update python/ql/lib/change-notes/released/0.3.0.md 2022-05-12 11:43:39 +01:00
Mathias Vorreiter Pedersen
b069d1bd17 Update python/ql/lib/CHANGELOG.md 2022-05-12 11:43:33 +01:00
Mathias Vorreiter Pedersen
eb3a35eaea Update java/ql/src/change-notes/released/0.1.2.md 2022-05-12 11:43:27 +01:00
Mathias Vorreiter Pedersen
11707f8522 Update java/ql/src/CHANGELOG.md 2022-05-12 11:43:19 +01:00
Mathias Vorreiter Pedersen
2ef976a152 Update java/ql/src/CHANGELOG.md 2022-05-12 11:43:08 +01:00
Mathias Vorreiter Pedersen
22bdde6eaa Update java/ql/lib/change-notes/released/0.2.1.md 2022-05-12 11:43:01 +01:00
Mathias Vorreiter Pedersen
e9e8f3810b Update java/ql/lib/CHANGELOG.md 2022-05-12 11:41:20 +01:00
Mathias Vorreiter Pedersen
1f7eefe95c Update java/ql/lib/CHANGELOG.md 2022-05-12 11:41:13 +01:00
github-actions[bot]
ee9980b31c Release preparation for version 2.9.2 2022-05-12 10:17:28 +00:00
Anders Schack-Mulligen
e0c74d4390 Merge pull request #9124 from github/workflow/coverage/update
Update CSV framework coverage reports
2022-05-12 09:06:07 +02:00
Anders Schack-Mulligen
fad7d9ae72 Merge pull request #9120 from igfoo/igfoo/fixes
Kotlin: Fix some alerts
2022-05-12 08:29:34 +02:00
Erik Krogh Kristensen
6014614a31 Merge pull request #9103 from erik-krogh/nextParam
JS: add support for typed NextJS route-handlers
2022-05-12 08:18:26 +02:00
github-actions[bot]
acaf4517c0 Add changed framework coverage reports 2022-05-12 00:17:30 +00:00
Chris Smowton
85dc1090fe Merge pull request #9116 from smowton/smowton/feature/accept-conditional-cookie-security
Java: tolerate `cookie.setSecure(request.isSecure())`
2022-05-11 21:29:14 +01:00
Tom Hvitved
46ab25b61e Merge pull request #9098 from aschackmull/dataflow/perf
Dataflow: Performance fixes
2022-05-11 20:41:48 +02:00
Ian Lynagh
33e17f1665 Kotlin: Fix some alerts 2022-05-11 17:58:50 +01:00
Ian Lynagh
cfde0a1491 Merge pull request #9109 from igfoo/igfoo/kotlin_merge
Initial Kotlin support
2022-05-11 16:16:22 +01:00
Tony Torralba
5be30209c1 Merge pull request #9036 from luchua-bc/java/hardcoded-jwt-key
Java: CWE-321 Query to detect hardcoded JWT secret keys
2022-05-11 16:31:34 +02:00
Henry Mercer
6ecc542ca3 Merge pull request #9117 from github/henrymercer/java/tag-telemetry
Java: Tag telemetry queries with `telemetry`
2022-05-11 15:13:35 +01:00
Henry Mercer
a626078423 Merge pull request #9118 from github/henrymercer/csharp/tag-telemetry
C#: Tag telemetry queries with `telemetry`
2022-05-11 15:13:29 +01:00
Anders Schack-Mulligen
4884520ee1 Dataflow: Review fix. 2022-05-11 15:40:49 +02:00
Chris Smowton
f7e1f3e1a5 Remove URL fragment from Google search 2022-05-11 14:38:09 +01:00
Tom Hvitved
333780e635 Merge pull request #8898 from hvitved/dataflow/clear-expect-summary-components
Data flow: Introduce 'with/without content' summary components
2022-05-11 15:16:42 +02:00
Ian Lynagh
c0a755e061 Merge remote-tracking branch 'upstream/main' into igfoo/kotlin_merge
Resolving conflicts:
	java/ql/lib/semmle/code/java/Expr.qll
2022-05-11 14:13:09 +01:00
Rasmus Wriedt Larsen
46f309c373 Merge pull request #6360 from jorgectf/jorgectf/python/insecure-cookie
Python: Add cookie security-related queries
2022-05-11 14:47:11 +02:00
Henry Mercer
b6f1ddcdab Java: Tag telemetry queries with telemetry
This will exclude the results of these queries from the summary tables
produced by `codeql database analyze` in a future version of the CodeQL
CLI.
2022-05-11 13:29:25 +01:00
Henry Mercer
cdd6e0e104 C#: Tag telemetry queries with telemetry
This will exclude the results of these queries from the summary tables
produced by `codeql database analyze` in a future version of the CodeQL
CLI.
2022-05-11 13:27:49 +01:00
Rasmus Wriedt Larsen
cff950f5f7 Python: Fix select of py/insecure-cookie 2022-05-11 14:06:30 +02:00
Anders Schack-Mulligen
9a4d86e9b4 Merge pull request #8571 from Marcono1234/marcono1234/statement-expression
Java: Add `ValueDiscardingExpr`
2022-05-11 13:37:24 +02:00
Rasmus Wriedt Larsen
fc8633cc01 Python: Fix select for py/cookie-injection 2022-05-11 13:18:14 +02:00
Chris Smowton
0044326884 Add change note 2022-05-11 12:06:27 +01:00
Chris Smowton
c17ef42cc7 Insecure cookie query: accept ServletRequest.isSecure(), and allow more than one possible input to a setSecure(...) call. 2022-05-11 11:59:37 +01:00
luchua-bc
f85c01c975 Correct string source 2022-05-11 10:37:22 +00:00
Chris Smowton
1af0e9b619 Servlets.qll: don't use deprecated library visiblity modifier. 2022-05-11 11:31:14 +01:00
Arthur Baars
a47e429945 Merge pull request #8909 from aibaars/tree-sitter-update
Tree sitter update
2022-05-11 12:02:14 +02:00
Rasmus Wriedt Larsen
add6579385 Merge pull request #9022 from RasmusWL/ruby-fix
Ruby: Fix `isLocalSourceNode` implementation
2022-05-11 11:52:44 +02:00
Rasmus Wriedt Larsen
27b99c51e9 Python: Add placeholder precision for py/insecure-cookie 2022-05-11 11:36:06 +02:00
Rasmus Wriedt Larsen
a902d3d8f0 Python: Add security-severity for py/insecure-cookie
Matching the Java query
7d4767a4f5/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql (L7)
2022-05-11 11:34:16 +02:00
Rasmus Wriedt Larsen
84ad45c665 Python: Fix Django import 2022-05-11 11:33:35 +02:00
Rasmus Wriedt Larsen
d127d2164a Merge branch 'main' into jorgectf/python/insecure-cookie 2022-05-11 11:13:47 +02:00
Anders Schack-Mulligen
25336df302 Merge pull request #8873 from atorralba/atorralba/android-startactivity-flowstep
Java: Add flow step from startActivity to getIntent
2022-05-11 11:08:08 +02:00
Anders Schack-Mulligen
c217a1e502 Update java/ql/lib/semmle/code/java/Expr.qll 2022-05-11 11:03:13 +02:00
Tony Torralba
43b425d0e4 Merge pull request #9002 from atorralba/atorralba/https-urls-improvs
Java: Add OkHttp and Retrofit models
2022-05-11 10:48:08 +02:00
Arthur Baars
907c3db5ca Address comments
Co-authored-by: Nick Rolfe <nickrolfe@github.com>
2022-05-11 09:59:42 +02:00
Erik Krogh Kristensen
5e02a76dfd add support for typed NextJS route-handlers 2022-05-11 09:45:34 +02:00
Cornelius Riemenschneider
506e09ef32 Merge pull request #9105 from github/criemen/dotnet-lua-tracing-config
C#: Lua tracing config: Use API function.
2022-05-11 09:28:09 +02:00
Erik Krogh Kristensen
872b275bd4 Merge pull request #9110 from erik-krogh/qlPackAll
QL: add implicit -all to a query pack to match the CodeQL pack resolution
2022-05-10 23:41:26 +02:00
Erik Krogh Kristensen
a5acaeb59c QL: add implicit -all to a query pack to match the CodeQL pack resolution 2022-05-10 23:25:32 +02:00
Ian Lynagh
b7a0b56e41 Kotlin: Add a this. 2022-05-10 19:51:31 +01:00
Ian Lynagh
8a89251c4f Kotlin: Tweak dbscheme 2022-05-10 19:51:31 +01:00
Ian Lynagh
3662611b04 Kotlin: Fix compilation_finished upgrade script 2022-05-10 19:51:31 +01:00
Ian Lynagh
b5572422df Kotlin: Autoformat 2022-05-10 19:51:31 +01:00
Ian Lynagh
8b809459d9 Kotlin: Remove kotlin branch CI test 2022-05-10 19:51:31 +01:00
Ian Lynagh
ab2946cf10 Kotlin: Add release notes 2022-05-10 19:51:31 +01:00
Ian Lynagh
e1d832c2e9 Upgrades: All old diagnostics are generated by the Java extractor 2022-05-10 19:51:31 +01:00
Tamas Vajk
26dfca8010 Add DB upgrade scripts for diagnostics and compilation_finished 2022-05-10 19:51:31 +01:00
Tony Torralba
a5a31db835 Rename AnyEqualsExpr and AnyNotEqualsExpr 2022-05-10 19:51:31 +01:00
Tony Torralba
0e3db78eba Make GeneratedFileMarker an instance of JavadocElement 2022-05-10 19:51:31 +01:00
Tamas Vajk
4f256d2958 Change LambdaExpr::asMethod to return the big-arity invoke instead of the wrapper 2022-05-10 19:51:31 +01:00
Ian Lynagh
af3bc4f44d Kotlin: Apply review feedback 2022-05-10 19:51:31 +01:00
Ian Lynagh
2e3d2b8e11 Java: Use the Diagnostics class in DiagnosticsReporting.qll
We shouldn't use database types/tables directly in src/
2022-05-10 19:51:31 +01:00
Tamas Vajk
464d13775d Add QL doc for LambdaExpr::isKotlinFunctionN 2022-05-10 19:51:31 +01:00
Ian Lynagh
1151f79eca Kotlin: Apply some review feedback 2022-05-10 19:51:31 +01:00
Ian Lynagh
726a005cc2 Update java/ql/lib/semmle/code/java/Expr.qll
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2022-05-10 19:51:31 +01:00
Ian Lynagh
1a36b1ab53 Kotlin: Format queries 2022-05-10 19:51:31 +01:00
Ian Lynagh
efe3c0d1ea Kotlin: Performance tweak 2022-05-10 19:51:30 +01:00
Ian Lynagh
653e74d181 Kotlin: Performance tweak 2022-05-10 19:51:30 +01:00
Ian Lynagh
b9be79473a Kotlin: Performance tweak 2022-05-10 19:51:30 +01:00
Ian Lynagh
65afd0d776 Kotlin: Performance tweak 2022-05-10 19:51:30 +01:00
Ian Lynagh
f5c0b0ebfe Kotlin: Performance tweak 2022-05-10 19:51:30 +01:00
Ian Lynagh
e0053cd471 Kotlin: qlformat a query 2022-05-10 19:51:30 +01:00
Ian Lynagh
bfe36558c1 Java/Kotlin: Update stats 2022-05-10 19:51:30 +01:00
Ian Lynagh
43035aef2d Java: Add an upgrade script 2022-05-10 19:51:30 +01:00
Ian Lynagh
4a6c2c2914 Revert "Java: Add an upgrade script"
This reverts commit c964d3262bb344d6c8e55d9bf69ffe2291b2f2cf.
2022-05-10 19:51:30 +01:00
Tamas Vajk
e8b3bf55fa Code quality improvements 2022-05-10 19:51:30 +01:00
Tamas Vajk
749d606f84 Fix expected file of useless null check test 2022-05-10 19:51:30 +01:00
Tamas Vajk
465a85bb8c Explicitly check if a when expression is in the expected &&/|| form 2022-05-10 19:51:30 +01:00
Tamas Vajk
3af8273620 Modify extraction of &&/|| to resugar it from when expression 2022-05-10 19:51:30 +01:00
Tamas Vajk
d33224a058 Add test case for missing CFG successor 2022-05-10 19:51:30 +01:00
Tamas Vajk
b66a3141f6 Extract functions using their name from JvmName annotation 2022-05-10 19:51:30 +01:00
Tamas Vajk
a24753f552 Extract final modifier on local variables 2022-05-10 19:51:30 +01:00
Tamas Vajk
4efb87a7dd Extract enum entry initializers 2022-05-10 19:51:30 +01:00
Ian Lynagh
2647a45239 Kotlin: Fix TypeVariableHidesType performance regression 2022-05-10 19:51:30 +01:00
Tamas Vajk
fc5229a0a5 Extract type access expression for static field access in initializer 2022-05-10 19:51:29 +01:00
Tamas Vajk
c6a75957e9 Fix expected files, fix type access extraction of file level static declarations 2022-05-10 19:51:29 +01:00
Tamas Vajk
1e529b2563 Add missing type access expression for static field accesses 2022-05-10 19:51:29 +01:00
Tamas Vajk
246f228a3b Add static field access test 2022-05-10 19:51:29 +01:00
Tamas Vajk
f43296a157 Extract type access for enum value access 2022-05-10 19:51:29 +01:00
Tamas Vajk
b5c8d29e40 Extract enum field declarations 2022-05-10 19:51:29 +01:00
Tamas Vajk
d6cbcdc847 Extract type access expression for parameter types 2022-05-10 19:51:29 +01:00
Tamas Vajk
f557719fe5 Extract type access expression for function return types 2022-05-10 19:51:29 +01:00
Tamas Vajk
dcac285a99 Add type access tests 2022-05-10 19:51:29 +01:00
Chris Smowton
7ef9420bfd Accept test changes 2022-05-10 19:51:29 +01:00
Chris Smowton
23e3bbea73 Fix: don't treat local classes as unspecialised
This shouldn't matter either way since they can't be subject to external references
2022-05-10 19:51:29 +01:00
Chris Smowton
4477482990 Share a class instance, not just a label 2022-05-10 19:51:29 +01:00
Chris Smowton
11fed0b4f8 Adjust test expectations 2022-05-10 19:51:29 +01:00
Chris Smowton
d63124a761 Extract a generic specialisation using its own type parameters in the same order like an unbound type
This replicates an oddity in the Java extractor that it doesn't differentiate a specialisation Generic<T1, T2, ...> from the unbound type, if T1, T2, ... are Generic's declared type variables occurring in the same order. For example, in `class MyList<T> { void addAll(MyList<T> param) { ... } }`, the type of `param` is an instantiated type, but
gets extracted as an unbound type. This commit can be reverted (except for the improvement to isUnspecialised) if/when that is fixed.
2022-05-10 19:51:29 +01:00
Chris Smowton
f3bd89a5cf Adjust test expectations 2022-05-10 19:51:29 +01:00
Chris Smowton
375199508e Always extract static initializers if a class has static members
This may not be necessary for anonymous objects, but it is certainly unrelated to `init { ... }` blocks.
2022-05-10 19:51:29 +01:00
Chris Smowton
e21a60bb4b Only extract anonymous init blocks in an instance initializer context 2022-05-10 19:51:29 +01:00
Chris Smowton
a317dc4246 Extract field initializers 2022-05-10 19:51:29 +01:00
Chris Smowton
9e8e99f4c3 Add interface-delegate test 2022-05-10 19:51:28 +01:00
Chris Smowton
5219ead4d4 Plugin version selection: fix test polarity and use integer not string comparison
(Otherwise we'll think that 1.6.10 comes before 1.6.9, for example.) This now implements the desired test: pick a version that exactly matches major and minor versions and which is the least patchlevel that is >= the target compiler.
2022-05-10 19:51:28 +01:00
Chris Smowton
d8b163a589 Fix running on patchlevel versions below the highest of that minor version
(For example, picking 1.6.10 to match the host kotlinc when both 1.6.10 and 1.6.20 are available)
2022-05-10 19:51:28 +01:00
Chris Smowton
62f39d7a22 Add test expectation 2022-05-10 19:51:28 +01:00
Chris Smowton
bfe3722018 Extract synthetic coroutine classes 2022-05-10 19:51:28 +01:00
Chris Smowton
a740ead56d Populate files table once per file, per trap file
Otherwise there's a chance the other trap file we're relying upon to populate the files table on our behalf gets overwritten (e.g. superceded by a newer .class file or more appropriate extractor) and we end up with a dangling reference.

This adds only populating the tables when the label is new, to avoid emitting files entries every single time a generic class specialisation is mentioned.
2022-05-10 19:51:28 +01:00
Ian Lynagh
b35b74779a Revert "Fix CFG construction of ExprStmt and StmtExpr"
This reverts commit db8d718cdbf0bef9cdf246221a921b99d4b22bea.

It broke ql/java/ql/test/library-tests/successors/TestDeclarations
2022-05-10 19:51:28 +01:00
Ian Lynagh
d2f6871868 Revert "Fix ExprStmt and StmtExpr in Boolean context"
This reverts commit 8a42837578e1c4361ed25682312ea5497ad0a12e.
2022-05-10 19:51:28 +01:00
Ian Lynagh
3aa25013c8 C#: CastingExpr is no longer needed in the main libraries 2022-05-10 19:51:28 +01:00
Tamas Vajk
82b937dedd Add query and script to plot CFG from DB 2022-05-10 19:51:28 +01:00
Tamas Vajk
037d66de15 Fix ExprStmt and StmtExpr in Boolean context 2022-05-10 19:51:28 +01:00
Ian Lynagh
385691287f C#: Define CastingExpr 2022-05-10 19:51:28 +01:00
Tamas Vajk
8282e57db5 Fix CFG construction of ExprStmt and StmtExpr 2022-05-10 19:51:28 +01:00
Tamas Vajk
81cb81366b Add test case for CFG issue with && in if condition 2022-05-10 19:51:28 +01:00
Tamas Vajk
10ef737a60 Adjust kotlin CI job 2022-05-10 19:51:28 +01:00
Tamas Vajk
953c6fdb7b Fix expected test file 2022-05-10 19:51:28 +01:00
Tamas Vajk
47799ae040 Code quality improvements + add dedicated DeadRefTypes test 2022-05-10 19:51:28 +01:00
Tamas Vajk
cdc7ed0e14 Extract container of adapter function as compiler generated 2022-05-10 19:51:28 +01:00
Tamas Vajk
7f94495601 Add test for adapter function 2022-05-10 19:51:28 +01:00
Tamas Vajk
fc66b73e3b Extract override modifier for lambda and reflection-like constructs 2022-05-10 19:51:28 +01:00
Tamas Vajk
505ccbbcf6 Extract override modifier 2022-05-10 19:51:28 +01:00
Tamas Vajk
92de139805 Add override tests 2022-05-10 19:51:27 +01:00
Tamas Vajk
ca99cb4999 Code quality improvements 2022-05-10 19:51:27 +01:00
Tamas Vajk
22af7f0e89 Remove duplications of locatable and element in the DB scheme 2022-05-10 19:51:27 +01:00
Ian Lynagh
400654d326 Kotlin: Add latest-url to kotlin_plugin_versions.py 2022-05-10 19:51:27 +01:00
Tamas Vajk
6ab86a1f46 Fix expected test files after 1.6.20 upgrade 2022-05-10 19:51:27 +01:00
Tamas Vajk
4e93134225 Add 1.6.20 support 2022-05-10 19:51:27 +01:00
Ian Lynagh
ff35088b49 Java: Add an upgrade script 2022-05-10 19:51:27 +01:00
Ian Lynagh
843310c466 Kotlin: Remove incorrect upgrade 2022-05-10 19:51:27 +01:00
Tamas Vajk
ad11b3e84a Add consistency query to verify we always have qualifier for calls 2022-05-10 19:51:27 +01:00
Tamas Vajk
4f3e89dd49 Fix expected test file 2022-05-10 19:51:27 +01:00
Tamas Vajk
a1842f9f17 Remove ExtensionMethodAccess and revert all dataflow changes 2022-05-10 19:51:27 +01:00
Tamas Vajk
95cb0149a3 Fix data flow through ExtensionMethodAccess 2022-05-10 19:51:27 +01:00
Tamas Vajk
38ab7acf3e Revert "Remove ExtensionMethodAccess to see extension method flows"
This reverts commit 9df4f2074379ba4668054a2a66eaaaaf5cb9b6c8.
2022-05-10 19:51:27 +01:00
Tamas Vajk
a9711b8c88 Remove ExtensionMethodAccess to see extension method flows 2022-05-10 19:51:27 +01:00
Tamas Vajk
6fccbaa93b Add extension method dataflow tests 2022-05-10 19:51:27 +01:00
Ian Lynagh
fac3699a5b Kotlin: Generate stats 2022-05-10 19:51:27 +01:00
Ian Lynagh
19270369c8 Java: Add an upgrade script 2022-05-10 19:51:27 +01:00
Ian Lynagh
c1629530e5 Kotlin: Fix build on Windows 2022-05-10 19:51:27 +01:00
Chris Smowton
de9648e515 Accept test changes
- generics gains extra excluded generic "specialisations" (specifically raw types)
- java_properties stops overwriting the Java extractor's output, which specifically flags isDefConstructor which kotlinc does not
- types naturally gains a lot of new raw types
2022-05-10 19:51:27 +01:00
Chris Smowton
239aab67b6 Populate the files table for generic class instances
This is because different instances might see the code in different locations (e.g., the class file exists in more than one jar) or with no location (seen as a .java file passed to kotlinc).

While I'm there, improve the order of checks and fix a trivial bug in withFileOfClass
2022-05-10 19:51:26 +01:00
Chris Smowton
db9ab22437 Erasure: produce raw types, not unbound types
This affects the trap labels for methods, and therefore consistency with the Java extractor.

TODO: check whether we can unify `erase` and `toRawType` entirely.
2022-05-10 19:51:26 +01:00
Chris Smowton
97d44d9583 Ensure external class extractions without a VirtualFile are lowest priority
Previously by using major version 0 to represent the no-virtual-file case these got highest priority. This meant that a class extracted relating to a .java file seen by the Kotlin compiler, which necessarily lacks a useful source-location, was highest priority. Now that should get overwritten whenever anybody sees it in the form of a .class
file, since this will have version information.

This should in particular eliminate the case where a generic class is extracted with no useful source location (based on .java source), then generic instances are extracted with a useful source location (based on a .class source), but the location isn't in the database.
2022-05-10 19:51:26 +01:00
Tamas Vajk
613d81d231 Extract static modifier and missing type access qualifier for static calls 2022-05-10 19:51:26 +01:00
Ian Lynagh
4cfda638cb Kotlin: Use -Xopt-in=kotlin.RequiresOptIn when compiling 2022-05-10 19:51:26 +01:00
Ian Lynagh
37cf36bc33 Kotlin: useDeclarationParent: Don't use fakeLabel 2022-05-10 19:51:26 +01:00
Ian Lynagh
5c8e0ff49b Kotlin: extractTypeParameter: Don't use fakeLabel 2022-05-10 19:51:26 +01:00
Tamás Vajk
48b6c61fdb Quality improvement: add explicit this in QL
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2022-05-10 19:51:26 +01:00
Tamas Vajk
e0afaa462e Fix Parameter.getACallArgument for parameters of extension methods 2022-05-10 19:51:26 +01:00
Ian Lynagh
1e8d077522 Kotlin: Fix some warnings 2022-05-10 19:51:26 +01:00
Ian Lynagh
f75e711474 Kotlin: Make the build noisier
We need to capture output for some commands we run during the build,
but this ended up being refactored so that we ate the output for all
commands. This means that we don't see warnings from the compiler.

Now we not only show the output, but we also print what commands we are
running.
2022-05-10 19:51:26 +01:00
Ian Lynagh
05c062da99 Kotlin: Stop useValueDeclaration returning fakeLabel 2022-05-10 19:51:26 +01:00
Ian Lynagh
c5e73cd6df Kotlin: Add TypeResult.cast() 2022-05-10 19:51:26 +01:00
Ian Lynagh
86c31cb2e8 Kotlin: Add Label.cast() 2022-05-10 19:51:26 +01:00
Tamas Vajk
c89f3163f9 Revert PrintAst changes related to wrong locations 2022-05-10 19:51:26 +01:00
Tamas Vajk
026ce2a27a Fix location of parameters in methods of parameterized types 2022-05-10 19:51:26 +01:00
Tamas Vajk
bfcd553c6c Change location of properties inside parameterized types 2022-05-10 19:51:26 +01:00
Tamas Vajk
0726b6410f Change location of methods inside parameterized types 2022-05-10 19:51:26 +01:00
Tamas Vajk
3813e6fc10 Fix expected files 2022-05-10 19:51:26 +01:00
Tamas Vajk
acb310e46a Change parameterized type location to the class file 2022-05-10 19:51:26 +01:00
Tamas Vajk
53f484cd98 Add test for inconsistent generic instantiation locations 2022-05-10 19:51:26 +01:00
Tamas Vajk
49bf53da5d Make extracted file class public and final 2022-05-10 19:51:25 +01:00
Ian Lynagh
77fec17a36 Kotlin: Autoformat QL 2022-05-10 19:51:25 +01:00
Ian Lynagh
c5e3aefe10 Kotlin: Fix build on Mac (Arm)
We were getting:

$ echo foo > bar
$ jar -c -f baz.jar bar
-f : no such file or directory
baz.jar : no such file or directory
K-*��ϳR0�3��r.JM,IM�u�MEX��)h8������y�xk�r�rPYJO�?y_wTbarK���P�e2`wT    META-INF/�`wTYJO�??=META-INF/MANIFEST.My_wT�e2~�barPK��
2022-05-10 19:51:25 +01:00
Ian Lynagh
7c571dd551 Kotlin: Allow decoding errors
If an error happens, we'd rather see /something/ than get a decoding
error.
2022-05-10 19:51:25 +01:00
Ian Lynagh
aed32cd69b C#: Autoformat 2022-05-10 19:51:25 +01:00
Tony Torralba
f8ad93a530 Add test case for local variable in anonymous init
Also fix another instance of the same issue in extractLocalTypeDeclStmt
2022-05-10 19:51:25 +01:00
Tony Torralba
1926bef050 Don't extract static init when the class already contains an anonymous init 2022-05-10 19:51:25 +01:00
Tony Torralba
3920b64d62 Add support for live literals 2022-05-10 19:51:25 +01:00
Tony Torralba
1f812f856c Extract static initializers of inner classes 2022-05-10 19:51:25 +01:00
Tamas Vajk
8c50e857e4 Add comments to clarify JVM type substitution for invoke methods 2022-05-10 19:51:25 +01:00
Tamas Vajk
1317d2d578 Fix DB inconsistencies with KFunction and KFunction::invoke call extraction 2022-05-10 19:51:25 +01:00
Tamas Vajk
0b4cf6ec82 Adjust extractEnclosingClass extraction 2022-05-10 19:51:25 +01:00
Tamas Vajk
44c8249a33 Remove outdated TODO comments 2022-05-10 19:51:25 +01:00
Tamas Vajk
5f729f8131 Merge two implementation of enclosing class extraction 2022-05-10 19:51:25 +01:00
Tamas Vajk
fe9333898f Minor code quality improvements 2022-05-10 19:51:25 +01:00
Tamas Vajk
f12bcc5715 Add dataflow test for property reference being used as lambda 2022-05-10 19:51:25 +01:00
Tamas Vajk
257224aa59 Change base class of property reference classes 2022-05-10 19:51:25 +01:00
Tamas Vajk
cf0be05b44 Add property reference invoke method implementation 2022-05-10 19:51:25 +01:00
Tamas Vajk
abcb367495 Add dataflow tests for lambda-like constructs
This commit adds tests for dataflow involving lambdas, big-arity lambdas, SAM conversions, and function references.
2022-05-10 19:51:25 +01:00
Chris Smowton
aab271d81e Fix extraction of data classes with array members
These use compiler-internal intrinsics at the IR layer, which are later lowered to java.util.Arrays calls. This performs that lowering in the same manner.
2022-05-10 19:51:25 +01:00
Chris Smowton
ae2ca183cc Improve logging when function resolution fails 2022-05-10 19:51:25 +01:00
Ian Lynagh
7dfd99d873 Kotlin: Accept test changes 2022-05-10 19:51:25 +01:00
Ian Lynagh
dbc5e73709 Kotlin: Add a test for annotation classes 2022-05-10 19:51:24 +01:00
Ian Lynagh
34f8d9b9b7 Kotlin: Handle annotation classes
Fixes:

[TYPES_NOT_DISJOINT] Base types @class and @interface are not disjoint. A common value is 225832
    Relevant element: id=225832
        Full ID for 225832: @"class;kotlin.internal.LowPriorityInOverloadResolution"

when Kotlin and Java both see such a class.
2022-05-10 19:51:24 +01:00
Ian Lynagh
b4d04f62b2 Kotlin: Log to the right TRAP file
Diagnostics for external classes were ending up in the source file's
TRAP file, and then breaking because `#compilation` isn't defined.
2022-05-10 19:51:24 +01:00
Tamas Vajk
91b7de42ad Make generated invoke/get/set public
The generated `invoke`/`get`/`set` methods are implementing interface members, so they need to be `public`.
2022-05-10 19:51:24 +01:00
Tamas Vajk
878352f69c Add test for checking generated invoke/get/set visibility 2022-05-10 19:51:24 +01:00
Chris Smowton
61b0efb401 Add test case 2022-05-10 19:51:24 +01:00
Chris Smowton
96908d153d Accept and amend check for anonymous types with type parameters 2022-05-10 19:51:24 +01:00
Chris Smowton
c0f3988aaa Tolerate nullable references to anonymous classes
This also adds a test case illustrating when this can arise
2022-05-10 19:51:24 +01:00
Chris Smowton
8d6ae50d21 Don't try to assign comments to fake overrides 2022-05-10 19:51:24 +01:00
Chris Smowton
613e6b29a9 Don't log every time a type alias is ignored
This is a known TODO; runtime output not required.
2022-05-10 19:51:24 +01:00
Tamas Vajk
5a5d0e15eb Extract calls to big-arity lambda's invoke by converting the artificial invoke to the existing one
Big arity lambda calls in IR look like standard method calls to an `invoke` with N arguments. However, this method doesn't exist in JVM, so instead we need to extract a call to `FunctionN.invoke(Object[])`.
2022-05-10 19:51:24 +01:00
Tamas Vajk
c6bc501207 Fix expected test file 2022-05-10 19:51:24 +01:00
Tamas Vajk
222f2415e2 Fix local function reference extraction 2022-05-10 19:51:24 +01:00
Ian Lynagh
62d9b85b46 Kotlin: This might fix building on Windows 2022-05-10 19:51:24 +01:00
Ian Lynagh
967619f26a Kotlin: Remove non-ascii character 2022-05-10 19:51:24 +01:00
Ian Lynagh
f138ba5246 C#/Kotlin: Sync SignAnalysisCommon.qll 2022-05-10 19:51:24 +01:00
Chris Smowton
9f294d1ecd Adjust more test expectations 2022-05-10 19:51:24 +01:00
Chris Smowton
2ea1a6c1f0 Adjust test expectations
These all just refer to re-adding empty blocks for classes whose constructors have no initializer statements for simplicity's sake.
2022-05-10 19:51:24 +01:00
Chris Smowton
35d213afc0 Extract varargs constructors 2022-05-10 19:51:24 +01:00
Chris Smowton
e24d78ae14 Create instance variable initializer block eagerly
Otherwise when the init block is followed by other constructor statements we can get a gap in a BasicBlock's child sequence due to the child init block never getting created at all.
2022-05-10 19:51:23 +01:00
Chris Smowton
9fd9894f6a Move abbreviation to external-decl extractor; record full signature. 2022-05-10 19:51:23 +01:00
Chris Smowton
1a656af96a Make truncation consistent 2022-05-10 19:51:23 +01:00
Chris Smowton
1b91a35df0 Truncate (but keep unique-ish) the names of very long file declarations 2022-05-10 19:51:23 +01:00
Tamas Vajk
b26044b327 Change extension receiver this access to be a parameter access 2022-05-10 19:51:23 +01:00
Tamas Vajk
21f6867cd4 Add test cases for delegating properties to other properties 2022-05-10 19:51:23 +01:00
Tamas Vajk
2f0ad50c08 Adjust trap file names of external file class declarations 2022-05-10 19:51:23 +01:00
Tamas Vajk
f5383bbc17 Add extension receiver type to function signature in trap file names 2022-05-10 19:51:23 +01:00
Ian Lynagh
61728e6a69 Kotlin: Tweak kotlin_plugin_versions.py 2022-05-10 19:51:23 +01:00
Ian Lynagh
0610917435 Kotlin: Workaround for CI on Windows 2022-05-10 19:51:23 +01:00
Ian Lynagh
ef5950197d Kotlin: Broaden isFake 2022-05-10 19:51:23 +01:00
Ian Lynagh
aee74dd570 Kotlin: Be more consistent in how we deal with "fake" elements 2022-05-10 19:51:23 +01:00
Ian Lynagh
8f85f5552b Kotlin: Accept test changes 2022-05-10 19:51:23 +01:00
Ian Lynagh
1ff6ada955 Kotlin: Tweak logging 2022-05-10 19:51:23 +01:00
Tamas Vajk
d6feb58bfc Fix property references to fake overrides 2022-05-10 19:51:23 +01:00
Tony Torralba
4eb1e3a47b Update ExtensionMethodAccess QLDoc 2022-05-10 19:51:23 +01:00
Tony Torralba
fcb334180d Create ExtensionMethodAccess class 2022-05-10 19:51:23 +01:00
Ian Lynagh
270beecef5 Kotlin: Write diagnostics to the write TRAP file
When a TRAP writer wrote a warning, it was going to the wrong TRAP
file.
2022-05-10 19:51:23 +01:00
Ian Lynagh
62ce28eb68 Kotlin: Populate diagnostic_for 2022-05-10 19:51:23 +01:00
Tamas Vajk
ac3c635fe3 Extract set function for field accessing property references 2022-05-10 19:51:23 +01:00
Tamas Vajk
a6f036d94e Extract property references with only backing field 2022-05-10 19:51:23 +01:00
Tamas Vajk
90ca47a46b Extract local delegated property reference 2022-05-10 19:51:23 +01:00
Ian Lynagh
47d8eb458e Kotlin: Improve top-level error handling 2022-05-10 19:51:23 +01:00
Ian Lynagh
a653054eb3 Kotlin: Make sure the context is empty when it should be 2022-05-10 19:51:23 +01:00
Ian Lynagh
3f4f0e5bec Kotlin: Accept test changes 2022-05-10 19:51:22 +01:00
Ian Lynagh
43a92f60b2 Kotlin: Give context to diagnostics
We now get e.g.

[2022-03-09 13:59:04 K] [ERROR] Diagnostic(com.github.codeql.KotlinUsesExtractor.useSimpleType(KotlinUsesExtractor.kt:505)): Type alias ignored for <root>.Test<kotlin.String>{ <root>.Alias1<kotlin.String> }
  ...while extracting a function at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:7:1:7:41
  ...while extracting a function if real at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:7:1:7:41
  ...while extracting a declaration at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:7:1:7:41
  ...while extracting a file at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:1:1:8:0
2022-05-10 19:51:22 +01:00
Tamas Vajk
a7e6ec9d02 Add test case for delegated properties initialized through provideDelegate operator 2022-05-10 19:51:22 +01:00
Tamas Vajk
a3992950b1 Add delegated property call tests 2022-05-10 19:51:22 +01:00
Tamas Vajk
126d780f34 Add delegated property declaration test 2022-05-10 19:51:22 +01:00
Tony Torralba
a6326b69dc Update java/ql/lib/config/semmlecode.dbscheme
Apply suggestion by @igfoo

Co-authored-by: Ian Lynagh <igfoo@github.com>
2022-05-10 19:51:22 +01:00
Tony Torralba
64531dd717 Fix AST representation of WhenExpr and WhenBranch 2022-05-10 19:51:22 +01:00
Tony Torralba
4b22e1a378 Extract WhenBranch as Stmt 2022-05-10 19:51:22 +01:00
Tony Torralba
10ab11cdf7 Handle WhenBranch CFG properly 2022-05-10 19:51:22 +01:00
Tony Torralba
5ea3228768 Fix test expectations 2022-05-10 19:51:22 +01:00
Tony Torralba
9735423c79 Fix WhenExpr flow 2022-05-10 19:51:22 +01:00
Tony Torralba
5979981199 Add test for missing WhenExpr flow 2022-05-10 19:51:22 +01:00
Tamas Vajk
d4701d72d9 Add DelegatedProperty QL class and use it in tests 2022-05-10 19:51:22 +01:00
Tamas Vajk
0ba2daf31a Adjust extraction to reuse KtProperty* relations 2022-05-10 19:51:22 +01:00
Tamas Vajk
78b4c9403d Add lazy local delegated property test case 2022-05-10 19:51:22 +01:00
Tamas Vajk
f8343b8cc7 Extract local delegated properties 2022-05-10 19:51:22 +01:00
Chris Smowton
48b99cf55c Don't try to attribute comments to the implicit this parameter. 2022-05-10 19:51:22 +01:00
Chris Smowton
6abb2529f5 Extract a clinit method for Kotlin files 2022-05-10 19:51:22 +01:00
Tamas Vajk
2d0bb43efe Do not extract local function containers as anonymous classes 2022-05-10 19:51:22 +01:00
Tamas Vajk
9597932112 Add test that calls a local function multiple times 2022-05-10 19:51:22 +01:00
Ian Lynagh
ea74803053 Kotlin: Add a comment 2022-05-10 19:51:22 +01:00
Ian Lynagh
44375fe1ae Kotlin: Add LoggerBase to the list of logging classes 2022-05-10 19:51:22 +01:00
Ian Lynagh
79c2ce7f1c Kotlin: Add tags to log messages (WARN, INFO, etc)
Makes it easier to see what's going on
2022-05-10 19:51:21 +01:00
Ian Lynagh
84c7b2310a Kotlin: Catch all Throwables
We want to try to continue even if we hit a stack overflow or an
assertion error.
2022-05-10 19:51:21 +01:00
Chris Smowton
8f929e2498 Avoid recursion through extractFunctionLaterIfExternalFileMember -> useType -> useDeclarationParent 2022-05-10 19:51:21 +01:00
Chris Smowton
1835022c84 Extract external file declarations to individual trap files 2022-05-10 19:51:21 +01:00
Ian Lynagh
2551bb58da Kotlin: Add a test of recursive instantiations
This used to cause a stack overflow
2022-05-10 19:51:21 +01:00
Ian Lynagh
0d79dfc412 Kotlin: Add a test of recursive instantiations
This used to cause a stack overflow
2022-05-10 19:51:21 +01:00
Ian Lynagh
90f7cc1223 Kotlin: Move anonymousTypeMapping and locallyVisibleFunctionLabelMapping
They're now in LabelManager, so they are shared between extractors.
2022-05-10 19:51:21 +01:00
Ian Lynagh
aad9e5601a Kotlin: Keep our own stack of extractor contexts
For now we only use its length, but in the future we might use this to
give more informatino about the cause of warnings.
2022-05-10 19:51:21 +01:00
Ian Lynagh
9c2df20117 Kotlin: When verbose, make with log when it starts and finishes doing something 2022-05-10 19:51:21 +01:00
Ian Lynagh
8b56302644 Kotlin: Add a concept of 'verbosity' 2022-05-10 19:51:21 +01:00
Ian Lynagh
cffcff93a8 Kotlin: Add a log message 2022-05-10 19:51:21 +01:00
Tamas Vajk
57d4d8e2a8 Code quality improvements 2022-05-10 19:51:21 +01:00
Tamas Vajk
7b2b40cc86 Fix type access extraction of nested generic constructor references 2022-05-10 19:51:21 +01:00
Tamas Vajk
46af85621a Add nested generic constructor reference test 2022-05-10 19:51:21 +01:00
Tamas Vajk
5e1ebb2545 Fix generic constructor reference extraction 2022-05-10 19:51:21 +01:00
Tamas Vajk
415fcaf605 Add generic constructor reference test 2022-05-10 19:51:21 +01:00
Tamas Vajk
b228ac4814 Code quality improvements 2022-05-10 19:51:21 +01:00
Tamas Vajk
91409534e2 Unify parameter order in type access extraction functions 2022-05-10 19:51:21 +01:00
Tamas Vajk
a8f595c50a Refactor type access extraction 2022-05-10 19:51:21 +01:00
Tamas Vajk
92e59a3ae1 Add SAM conversion tests 2022-05-10 19:51:21 +01:00
Tamas Vajk
eebfe56c95 Extract more type access expressions 2022-05-10 19:51:21 +01:00
Tamas Vajk
f730aa12b6 Refactor type access extraction for function references and lambdas 2022-05-10 19:51:21 +01:00
Tamas Vajk
a70ade224f Fix (generic) type access extraction for lambdas 2022-05-10 19:51:21 +01:00
Ian Lynagh
a8c94c500e Kotlin: Simplify PrimitiveTypeInfo
Removes a load of argument-passing
2022-05-10 19:51:20 +01:00
Ian Lynagh
0bf1ff9f2f Kotlin: Comments and tweaks in Label 2022-05-10 19:51:20 +01:00
Ian Lynagh
2c5dc42db4 Kotlin: Comments and tweaks to TrapWriter. 2022-05-10 19:51:20 +01:00
Ian Lynagh
b1ebcdd524 Kotlin: Add some warnings 2022-05-10 19:51:20 +01:00
Tamas Vajk
4af12e7c9d Change array.get calls to array indexing in FunctionN.invoke body 2022-05-10 19:51:20 +01:00
Tony Torralba
2da98148dc Add NotNullExpr flow 2022-05-10 19:51:20 +01:00
Tony Torralba
cf5152baa2 Add test for NotNullExpr flow 2022-05-10 19:51:20 +01:00
Tamas Vajk
4e18974889 Fix type access expression extraction for function/property references 2022-05-10 19:51:20 +01:00
Chris Smowton
73c5f8c591 Accept more test changes 2022-05-10 19:51:20 +01:00
Chris Smowton
f513fdce7b Accept test changes 2022-05-10 19:51:20 +01:00
Chris Smowton
dc64b536b3 Ensure that initializers are only printed once in a PrintAst run
Otherwise the output becomes a DAG not a tree. Java achieves the same by omitting all PrintAst of `<obinit>` routines.
2022-05-10 19:51:20 +01:00
Chris Smowton
13cd145a76 Retain Member.getInitializer for Kotlin programs
I opt to identify any syntactic initializer. These are broader in scope than Java's member initializers, which are necessarily context-free, whereas in Kotlin the primary constructor's parameters can be referred to.
2022-05-10 19:51:20 +01:00
Chris Smowton
37543e7a86 Switch to expanding property initializers and init blocks in-place
Pros:
* <obinit> no longer emitted: one less function per class
* Parameters to the primary constructor, if any, are no longer referred to out of scope
* Simple primary constructor `val` and `var` declarations work as expected

Cons:
* If there are multiple secondary constructors, no primary constructor and long init blocks, there could be considerable duplicate extraction of those init blocks. Hopefully this case is very rare.
2022-05-10 19:51:20 +01:00
Ian Lynagh
af7d809b8a Kotlin: Log to a file, not stdout
We shouldn't interfere with a build's stdout
2022-05-10 19:51:20 +01:00
Ian Lynagh
a112e9ab5c Kotlin: Add conditional dumping 2022-05-10 19:51:20 +01:00
Chris Smowton
8d8a2482f1 Accept test changes
These are just ordering changes because the bounds of assignment statements relative to their operands have changed.
2022-05-10 19:51:20 +01:00
Chris Smowton
789fe971e4 Fix locations and enclosing statement/callable for assignments 2022-05-10 19:51:20 +01:00
Ian Lynagh
cc0f5d8700 Kotlin: KotlinExtractorExtension tweaks
Added/fixed a load of comments.
Adjusted some function visibilities.
2022-05-10 19:51:20 +01:00
Tamas Vajk
67be6a18de Fix generic callable bindings inside invoke methods 2022-05-10 19:51:20 +01:00
Tamas Vajk
6742496fe3 Get type arguments for property/function references 2022-05-10 19:51:20 +01:00
Tamas Vajk
4b55dce0e9 Add generic function and property reference test cases 2022-05-10 19:51:20 +01:00
Tamas Vajk
18812c810c Add PropertyRefExpr QL class, change extraction to use it, and add tests 2022-05-10 19:51:19 +01:00
Tamas Vajk
5fea49a3c9 Merge function and property reference extraction logic in helper class 2022-05-10 19:51:19 +01:00
Tamas Vajk
b4b1976bc4 Add get/set method extraction for property references 2022-05-10 19:51:19 +01:00
Tamas Vajk
4ce813a720 Extract anonymous class for property references (class, constructor, call to constructor, optional parameters) 2022-05-10 19:51:19 +01:00
Tamas Vajk
d057530584 Add property reference tests 2022-05-10 19:51:19 +01:00
Chris Smowton
f3b92e7549 Explain why there is no syntheticToRealPropertyMap 2022-05-10 19:51:19 +01:00
Chris Smowton
110a2c7b87 Try our best to fix up the truncated class graph exposed by the Kotlin Android extensions plugin 2022-05-10 19:51:19 +01:00
Chris Smowton
2d1308980a Remove accidentally committed change 2022-05-10 19:51:19 +01:00
Chris Smowton
9671668782 Remove accidentally committed change 2022-05-10 19:51:19 +01:00
Chris Smowton
dbb7b0bbf0 Update control-flow test expectations 2022-05-10 19:51:19 +01:00
Chris Smowton
5fe65ed983 Extract no-when-branch-found calls
These are extracted as "throw new kotlin.NoWhenBranchFoundException();", which is the Java lowering of the intrinsic.

In the process, amend the control-flow graph to let when branches propagate `throw`s outwards, and similarly statement expressions.
2022-05-10 19:51:19 +01:00
Ian Lynagh
d09dff482c Kotlin: Add diagnostics table to the 'trap' test 2022-05-10 19:51:19 +01:00
Ian Lynagh
a512ee7ac1 Kotlin: Extend long-comment test 2022-05-10 19:51:19 +01:00
Ian Lynagh
f8673d86b5 Kotlin: Don't double-escape TRAP strings
The TrapWriter.write* functions are going to escape them for us.
2022-05-10 19:51:19 +01:00
Ian Lynagh
4454ef7f95 Kotlin: Add tests for long comments 2022-05-10 19:51:18 +01:00
Ian Lynagh
9af99c584e Kotlin: Tweak test 2022-05-10 19:51:18 +01:00
Ian Lynagh
dc7f8a6a5a Kotlin: Refactor TrapWriter/Logger
It's now Tpossible for TrapWriter to log warnings. This required a
little juggling to break the dependency loop between the two classes.
2022-05-10 19:51:18 +01:00
Ian Lynagh
1d824a4e2f Kotlin: Add a test for truncated literals 2022-05-10 19:51:18 +01:00
Ian Lynagh
6c19409804 Java/Kotlin: Add Diagnostics.qll 2022-05-10 19:51:18 +01:00
Ian Lynagh
0e689a9d35 Kotlin: Avoid name clash 2022-05-10 19:51:18 +01:00
Chris Smowton
da159d7239 Add test showing assign expressions 2022-05-10 19:51:18 +01:00
Chris Smowton
7cb6e19e44 Extract array update operations
These are of the form arrExpr[indexExpr] op= rhs
2022-05-10 19:51:18 +01:00
Tamas Vajk
d9c72b1c04 Fix changed expected file 2022-05-10 19:51:18 +01:00
Tamas Vajk
ff5bbee75a Change extracted base type of function references 2022-05-10 19:51:18 +01:00
Tamas Vajk
55428c0c3c Update test 2022-05-10 19:51:18 +01:00
Tamas Vajk
42803a161c WIP: add test for reflective calls 2022-05-10 19:51:18 +01:00
Tony Torralba
c4c254587e Add StmtExpr flow 2022-05-10 19:51:18 +01:00
Tony Torralba
b626e80a61 Add test for StmtExpr flow 2022-05-10 19:51:18 +01:00
Chris Smowton
8af0f26411 Extract simple in-place operators
Complex in-place operators (someFieldOrArrayCell += e) get a harder-to-parse lowering which needs to be intercepted at the IrBlock level
2022-05-10 19:51:18 +01:00
Chris Smowton
2fb54de269 Extract ordinary array get and set operations as ArrayAccesses, not calls 2022-05-10 19:51:18 +01:00
Tamas Vajk
387e8db161 Minor code quality improvements 2022-05-10 19:51:18 +01:00
Tamas Vajk
6154c2be18 Change arguments of big arity invoke call 2022-05-10 19:51:18 +01:00
Tamas Vajk
3f2c275e5f Fix functional interface selection 2022-05-10 19:51:18 +01:00
Tamas Vajk
46bd6b096e Add big arity SAM conversion test case 2022-05-10 19:51:18 +01:00
Tamas Vajk
8ab4335562 Add some error handling 2022-05-10 19:51:17 +01:00
Tamas Vajk
a598c7fc0c Rework SAM conversion extraction (handle arbitrary expression that's being converted) 2022-05-10 19:51:17 +01:00
Tamas Vajk
34ae00fa62 Extract SAM lambda conversion 2022-05-10 19:51:17 +01:00
Chris Smowton
377a0f91f0 Add missing times operator 2022-05-10 19:51:17 +01:00
Chris Smowton
96f3ea460f Make varargs extraction more Java-like:
* Extract varargs as if they are ordinary positional arguments
* Adapt the QL that distinguishes varargs from ordinary arguments to account for Kotlin's varargs which can occur in the middle of the arg list
* Add a test checking dataflow through varargs which doesn't work yet due to array-get and array-set not being extracted as IndexExprs
* Extract the special case arrayOf(*x) as a clone call, which is (equivalent to) the Java lowering of that operation
2022-05-10 19:51:17 +01:00
Chris Smowton
7368b49b16 Implement Any?.String using java.lang.String.valueOf
This is how kotlinc does it, and doesn't involve an unchecked null deref like the existing use of Object.toString.
2022-05-10 19:51:17 +01:00
Tamas Vajk
616f20fa52 Handle more cases of qualified this references 2022-05-10 19:51:17 +01:00
Chris Smowton
7fe260c1a2 Convert type-parameter-out-of-scope warning into consistency query
The warning in the extractor is inaccurate due to references to enclosing types' type parameters. A consistency query can check that the type parameter is indeed in scope exploiting broader knowledge of the enclosing types.
2022-05-10 19:51:17 +01:00
Chris Smowton
36356c2937 Make IntelliJ parse block TODO properly 2022-05-10 19:51:17 +01:00
Chris Smowton
2a6afff8ba Remove TODO for method source-declarations
This was resolved when method type arguments were implemented.
2022-05-10 19:51:17 +01:00
Chris Smowton
1ecbf8e84b Clean up and document erase function 2022-05-10 19:51:17 +01:00
Chris Smowton
65f3016a13 Note class-labelling todos resolved
Type arguments: yes outer classes can have arguments; they are appended after the full name.

String concatenation: this used to be worse before this unquoted version of the function existed; I think that's what the comment was complaining about.
2022-05-10 19:51:17 +01:00
Chris Smowton
7389e5d687 Note array type signatures are correctly extracted 2022-05-10 19:51:17 +01:00
Chris Smowton
38ad86f850 Note type substitution TODO done
`getUnquotedClassLabel` uses `useType` on its args to get their labels; consequently they get substituted for Java types as required.
2022-05-10 19:51:17 +01:00
Chris Smowton
d103bf65bd Remove inapplicable TODO re: K<->J type substitution
Turns out the two use cases the TODO worried about are already taken care of: `Unit` is replaced with `void` only in contexts where primitives can be used, and `List` and similar only have incompatible extension methods, which are declared by `CollectionsKt` not `List`. This is likely deliberate to enable the Kotlin <-> Java substitution to be implemented simply by kotlinc.
2022-05-10 19:51:17 +01:00
Chris Smowton
d593185a8c Quieten errors relating to generic type aliases
Turns out type aliases are always substituted by the compiler, with the `IrSimpleType.abbreviation` field indicating what the original alias was if any. Therefore we're already extracting the right types. This commit simply omits extracting a kt_type for a type alias that uses type parameters as this certainly won't work at present because we don't have IrTypes for the type parameters declared by the alias and used in its RHS.
2022-05-10 19:51:17 +01:00
Chris Smowton
1d47ea30eb Remove unused function 2022-05-10 19:51:17 +01:00
Chris Smowton
f6db91f294 Update test expectations 2022-05-10 19:51:17 +01:00
Chris Smowton
7dec3f4835 Use EqualityTest for either value or ref comparions, and ReferenceEqualityTest for strictly ref comparison. 2022-05-10 19:51:17 +01:00
Chris Smowton
f95effcf82 Always extract ValueEQ/NEExpr for Kotlin ==/!=
I introduce AnyEqualsExpr for either reference or value equality and AnyEqualityTest for the same concept including not-equals operators, and use them wherever the written QL clearly doesn't care about the difference between reference and value comparison, typically because it is concerned with testing against null or against a primitive constant.
2022-05-10 19:51:17 +01:00
Chris Smowton
a120fab9f7 Complete implementation of equality tests
- Create a new operator representing an infix value [in]equality test, equivalent to Objects.equals(lhs, rhs)
- Continue to use simple equality where it is clearly possible at the callsite
- Note that ieee754equals is the same as Java's == and != operators
2022-05-10 19:51:17 +01:00
Chris Smowton
b339cf7f2b Restore CI_TOKEN secret 2022-05-10 19:51:16 +01:00
Chris Smowton
658e6f4009 Try no token 2022-05-10 19:51:16 +01:00
Chris Smowton
f870805c0c Create test-kotlin.yml 2022-05-10 19:51:16 +01:00
Ian Lynagh
97793b58cd Kotlin: Tweak diagnostic writing
In particular, we now write full exception information, so we can
diagnose problems.

We were using `warn` to log errors in some cases, and generally using
lower-level functions than necessary. We now use the appropriate
functions. I've lost the distinction between e.g. ErrorHigh and ErrorSevere
in this, but we can add it back if it's important.
2022-05-10 19:51:16 +01:00
Ian Lynagh
48c4438a78 Kotlin: Rename the final warn function to diagnostic 2022-05-10 19:51:16 +01:00
Ian Lynagh
ee9f9bb07e Kotlin: Move a function 2022-05-10 19:51:16 +01:00
Ian Lynagh
79f80e6541 Kotlin: Rename CODEQL_EXTRACTOR_KOTLIN_WARNING_LIMIT to CODEQL_EXTRACTOR_KOTLIN_DIAGNOSTIC_LIMIT 2022-05-10 19:51:16 +01:00
Ian Lynagh
a25b411dd0 Kotlin: Rename "warning" to "diagnostic" a lot 2022-05-10 19:51:16 +01:00
Ian Lynagh
458cb850a7 Kotlin: Accept test changes 2022-05-10 19:51:16 +01:00
Ian Lynagh
9296bf3079 Kotlin: Write extractor name to TRAP file metadata 2022-05-10 19:51:16 +01:00
Chris Smowton
629af664c6 Explicitly specify whether a dispatch or an extension receiver is intended 2022-05-10 19:51:16 +01:00
Chris Smowton
377bd8f2e9 Extract String?.plus as either an AddExpr or a call to an intrinsic
If it is used by the compiler to implement the infix plus operator, resugar it and extract a `+` as Java would. If it is literally called by the user (e.g. `(if (x) then "not null" else null).plus(something)`), then extract a call to the real method Intrinsics.stringPlus (a two-arg static method).
2022-05-10 19:51:16 +01:00
Chris Smowton
93e8d5a2d6 Add tests for mutually-recursive types 2022-05-10 19:51:16 +01:00
Chris Smowton
8bb23651ae Extract type parameter bounds 2022-05-10 19:51:16 +01:00
Tamas Vajk
ec5bc8dad5 Add workaround for unbound symbols (get stub from descriptor) 2022-05-10 19:51:16 +01:00
Tamas Vajk
2965e780cc Add local dataflow test for string templates 2022-05-10 19:51:16 +01:00
Tony Torralba
6bd6097ed1 Add taint step for StringTemplateExpr 2022-05-10 19:51:16 +01:00
Tamas Vajk
b7914ed77b Code quality improvements 2022-05-10 19:51:16 +01:00
Tamas Vajk
695b3a6dbd Add fallback symbol lookup for IrFunctionReference extraction 2022-05-10 19:51:16 +01:00
Tamas Vajk
d495badc1e Rename companion object QL class 2022-05-10 19:51:16 +01:00
Tamas Vajk
535610452f Fix missing newline in DB scheme generator 2022-05-10 19:51:16 +01:00
Chris Smowton
b9d8fe72f0 TRAP formatting: adopt Java's standards
* Encode dates with D"" strings
* Truncate exceedingly long string values
* Note that floats don't require any special handling
2022-05-10 19:51:16 +01:00
Tamas Vajk
4adf5829e4 Fix expected files 2022-05-10 19:51:16 +01:00
Tamas Vajk
9ff9bbe1c5 Fix merge conflict 2022-05-10 19:51:16 +01:00
Tamas Vajk
b4beddf2f9 Introduce cast for <unsafe-coerce> calls 2022-05-10 19:51:15 +01:00
Ian Lynagh
8d754f5129 Kotlin: Fix bug in, and performance of, NullGuards::clearlyNotNullExpr 2022-05-10 19:51:15 +01:00
Ian Lynagh
03c1845053 Kotlin: Add a TODO comment 2022-05-10 19:51:15 +01:00
Ian Lynagh
76ca0b2776 Kotlin: Pull Kotlin type for localvars out into its own table 2022-05-10 19:51:15 +01:00
Ian Lynagh
7862229807 Kotlin: Pull Kotlin type for params out into its own table 2022-05-10 19:51:15 +01:00
Ian Lynagh
dc26abe341 Kotlin: Pull Kotlin type for methods/constrs out into their own tables 2022-05-10 19:51:15 +01:00
Ian Lynagh
ee008773dc Kotlin: Pull Kotlin type for fields out into its own table 2022-05-10 19:51:15 +01:00
Ian Lynagh
0f7f90dd4e Kotlin: Add a consistency query for Kotlin types 2022-05-10 19:51:15 +01:00
Ian Lynagh
86bf126ed8 Kotlin: Pull Kotlin type for expressions out into its own table 2022-05-10 19:51:15 +01:00
Tamas Vajk
cd5555a5dd Extract companion objects from interfaces 2022-05-10 19:51:15 +01:00
Tamas Vajk
53f40a3f31 Do not extract fake properties 2022-05-10 19:51:15 +01:00
Tamas Vajk
5c38b4e84d Extract expression body 2022-05-10 19:51:15 +01:00
Chris Smowton
4d408159aa When extracting a call to an inherited method, substitute the callee's type parameters appropriately. 2022-05-10 19:51:15 +01:00
Chris Smowton
8c9c37ca47 Revert "Kotlin: Extract fake overrides for now"
This reverts commit a1ffa7b66b6bc1a9b6fd93da60e7a16c0dc2fb21.
2022-05-10 19:51:15 +01:00
Ian Lynagh
16a27f5258 Kotlin: Provide a way for tests to cause an exception 2022-05-10 19:51:15 +01:00
Ian Lynagh
89eae2407b Kotlin: Improve error handling
Each compilation, and each file within a cmopilation, now gets a
"result" indicating whether it had recoverable or non-recoverable
errors.
2022-05-10 19:51:15 +01:00
Tamas Vajk
4c68b583de Do not report negative index warning on extension parameters 2022-05-10 19:51:15 +01:00
Ian Lynagh
8d15d0acfb Kotlin: Extract fake overrides for now
When we have Kotlin:

class A {
    fun foo(z: OB<G1, G2>.B<E1, E2>) {
        val foo = z.someFun()
    }
}

and Java:

public class OB<S1, S2> extends OC<F1, F2> {
        public class B<T1, T2> extends OC<F1, F2>.C<D1, D2, T1, T2> {
        }
}

class OC<U1, U2> {
        public class C<X1, X2, Y1, Y2> {
            int someFun() {
                return 5;
            }
        }
}

the `someFun` call is to a fake override, and has 4 type arguments.
If we treat it as calling the real function, then 6 type are expected,
and we get IndexOutOfBoundsException when we try to reorder the
type parameters in orderTypeArgsLeftToRight.

So for now, we just extract the fake overrides, so that we at least
don't crash.
2022-05-10 19:51:15 +01:00
Ian Lynagh
46ccd45833 Kotlin: Add tests for fake overrides 2022-05-10 19:51:15 +01:00
Chris Smowton
fdb1668cff CommentExtractor: use actual file label instead of hopefully correctly guessing its string form 2022-05-10 19:51:15 +01:00
Tamas Vajk
bb7e01988a Change kotlin dependency version from 1.6.0-RC2 to 1.6.10 2022-05-10 19:51:15 +01:00
Chris Smowton
0d90148f3e Prefer the Kotlin extractor's version of trap files 2022-05-10 19:51:15 +01:00
Chris Smowton
69c645a594 Log when a class version can't be read 2022-05-10 19:51:15 +01:00
Tamas Vajk
300719a07a Do not delete temp TRAP files when file level exception is caught 2022-05-10 19:51:14 +01:00
Tamas Vajk
82fe08ea8e Improve exception handling 2022-05-10 19:51:14 +01:00
Tamas Vajk
29f4eb96e1 Handle exceptions on file level 2022-05-10 19:51:14 +01:00
Ian Lynagh
468a911f83 Kotlin: Use with in a number more cases 2022-05-10 19:51:14 +01:00
Ian Lynagh
f985671d7f Kotlin: Make with an inline function 2022-05-10 19:51:14 +01:00
Ian Lynagh
3cc79f8b56 Kotlin: 'with' PoC 2022-05-10 19:51:14 +01:00
Ian Lynagh
2868644d36 Kotlin: Remove some code marked 'delete' 2022-05-10 19:51:14 +01:00
Ian Lynagh
4cf88e1a8d Kotlin: Remove some comments
These are now in Kotlin #38
2022-05-10 19:51:14 +01:00
Ian Lynagh
c62ad4b802 Kotlin: Pass dependencyCollector when making a new KotlinFileExtractor
I think this only wasn't done previously because it used to make a
KotlinSourceFileExtractor.
2022-05-10 19:51:14 +01:00
Ian Lynagh
5f176beb09 Kotlin: Refactoring: Use a more idiomatic way to prepend to a list 2022-05-10 19:51:14 +01:00
Ian Lynagh
8d2221ea60 Kotlin: getFunctionLabel: Add comments 2022-05-10 19:51:14 +01:00
Ian Lynagh
d1a0a9668f Kotlin: Remove a default argument
It was only defaulted in one case, and it's probably clearer to be
explicit.
2022-05-10 19:51:14 +01:00
Ian Lynagh
c125c1a698 Kotlin: getFunctionLabel: Make parentId be nullable
This allows us to simplify the set of functions.
2022-05-10 19:51:14 +01:00
Ian Lynagh
dd51141029 Kotlin: Use variable names more consistently 2022-05-10 19:51:14 +01:00
Ian Lynagh
2f8ede2ae5 Kotlin: Fix a variable shadowing warning 2022-05-10 19:51:14 +01:00
Ian Lynagh
72a6bfe7db Kotlin: getFunctionLabel: Small refactoring
We now pass the IrDeclarationParent of the function to the final
getFunctionLabel function, and that takes care of finding the
enclosing class.
2022-05-10 19:51:14 +01:00
Chris Smowton
27b0d579d0 Add compilation-units test 2022-05-10 19:51:14 +01:00
Chris Smowton
7a756e3be9 Extract compilation-unit package and location for class files 2022-05-10 19:51:14 +01:00
Chris Smowton
024f8c651e Accept test changes 2022-05-10 19:51:14 +01:00
Chris Smowton
863037ec41 Always extract methods of user-class supertypes
This matches the Java extractor's behaviour. Also if we re-visit a class to extract its members, revisit its supertypes to extract their members too.
2022-05-10 19:51:14 +01:00
Tamas Vajk
8f48c1b161 Add test for missing generic method 2022-05-10 19:51:14 +01:00
Chris Smowton
20d56094ee Note that unusedLocation can raise an alert for used but inaccessible locations 2022-05-10 19:51:13 +01:00
Ian Lynagh
920599fcf5 Kotlin: Make an unnecessarily-optional argument a required argument 2022-05-10 19:51:13 +01:00
Tamas Vajk
52597e5d63 Fix missing declarations in declaration stack 2022-05-10 19:51:13 +01:00
Tamas Vajk
482a37cfe3 Fix unbound symbol.owner references and add todos 2022-05-10 19:51:13 +01:00
Ian Lynagh
41c36760f7 Kotlin: Small refactorings and comments 2022-05-10 19:51:13 +01:00
Ian Lynagh
c0f194316f Kotlin: Update test following changes to casting operators 2022-05-10 19:51:13 +01:00
Ian Lynagh
ad33c47536 Kotlin: Add a test for Kotlin seeing Java code as properties 2022-05-10 19:51:13 +01:00
Ian Lynagh
579c590ea6 Kotlin: Accept test changes following "casting" operator changes 2022-05-10 19:51:13 +01:00
Ian Lynagh
6566f7b69f Kotlin: Add types for the different kinds of casts that Kotlin has
We might want to unify some of these in future, but doing that
correctly is easier than splitting them up correctly, so I've given each
one its own QL class for now.

I am not familiar with many of the libraries/queries that use CastExpr.
I've briefly looked at them and updated them in a way that looks
superficially reasonable, but some of the uses will probably want to be
refined later.
2022-05-10 19:51:13 +01:00
Ian Lynagh
7cf1289385 Kotlin: Fix build with old JDKs 2022-05-10 19:51:13 +01:00
Chris Smowton
221fa37081 Fix naming of local class instances that fall within generic functions 2022-05-10 19:51:13 +01:00
Ian Lynagh
735520a4ce Kotlin: Accept test changes in types test 2022-05-10 19:51:13 +01:00
Ian Lynagh
e9fcd4749a Kotlin: Use ASM9 rather than ASM7
This fixes
        exception: java.lang.UnsupportedOperationException: PermittedSubclasses requires ASM9
when we encounter ConstantDesc.class in the JDK's modules.
2022-05-10 19:51:13 +01:00
Tamas Vajk
646fc58c25 Fix expected test files 2022-05-10 19:51:13 +01:00
Tamas Vajk
44b731c68e Exclude extraction of fake overridden properties 2022-05-10 19:51:13 +01:00
Tamas Vajk
55b8e4400d Code quality improvements 2022-05-10 19:51:13 +01:00
Tamas Vajk
b6e5e1977d Extract more visibility modifiers 2022-05-10 19:51:13 +01:00
Ian Lynagh
a6d0dc7751 Kotlin: Small refactorings 2022-05-10 19:51:13 +01:00
Ian Lynagh
e1cff50c39 Kotlin: Remove KotlinSourceFileExtractor 2022-05-10 19:51:13 +01:00
Ian Lynagh
c1c4e4f86c Kotlin: Move extractFileContents into KotlinFileExtractor 2022-05-10 19:51:13 +01:00
Ian Lynagh
d43efd4cc7 Kotlin: KotlinSourceFileExtractor: Take filePath rather than file 2022-05-10 19:51:13 +01:00
Tamas Vajk
8e31bd8ec7 Update expected files after rebase 2022-05-10 19:51:13 +01:00
Tamas Vajk
9e21fa838e Test case for generic inner type instantiation 2022-05-10 19:51:13 +01:00
Chris Smowton
978978b86a Accept test changes 2022-05-10 19:51:13 +01:00
Chris Smowton
f4314c1f3d Substitute all generic types into function trap IDs and signatures, and ensure the subbed types are never primitive
The solution for ensuring they are primitive (making the range of the substitution always nullable) will need replacing once we export Kotlin types.
2022-05-10 19:51:12 +01:00
Chris Smowton
3365f3972e Instantiated generic type substitution: substitute outer class parameters too 2022-05-10 19:51:12 +01:00
Chris Smowton
fd495aa783 Name non-generic functions for their non-erased parameter types 2022-05-10 19:51:12 +01:00
Chris Smowton
f177c2c5ae Function trap ids: remove spaces between value parameters
Otherwise these won't match the IDs used by the Java extractor.
2022-05-10 19:51:12 +01:00
Chris Smowton
f38f03e6c9 Value parameters: provide correct source declaration 2022-05-10 19:51:12 +01:00
Chris Smowton
cd07cc448e Class trap labels: include outer type parameters 2022-05-10 19:51:12 +01:00
Chris Smowton
94efb427fe Type parameters: record index Java-style
Previously they received indices offset by the number of surrounding class type parameters.
2022-05-10 19:51:12 +01:00
Chris Smowton
178f128bdc Function labels: include <n> suffix (where n is the number of function type parameters)
This matches the Java extractor's behaviour.
2022-05-10 19:51:12 +01:00
Ian Lynagh
448b3d38d3 Kotlin: Duplicate less TRAP 2022-05-10 19:51:12 +01:00
Ian Lynagh
2f435a1a95 Kotlin: file_classes consistency check now passes 2022-05-10 19:51:12 +01:00
Ian Lynagh
368c330ecf Kotlin: Accept test changes following file-class fixes 2022-05-10 19:51:12 +01:00
Ian Lynagh
194e9fd2da Kotlin: Handle file classes better 2022-05-10 19:51:12 +01:00
Ian Lynagh
4340fe7044 Kotlin: Comments: Small refactoring 2022-05-10 19:51:12 +01:00
Tamas Vajk
b599ff2792 Change variable location extraction 2022-05-10 19:51:12 +01:00
Tamás Vajk
75e4b6c740 Fix typo in PrintAst.qll 2022-05-10 19:51:12 +01:00
Chris Smowton
33a9b4fb16 Add explanatory comment 2022-05-10 19:51:12 +01:00
Chris Smowton
e16a135a09 Add inner generic class test 2022-05-10 19:51:12 +01:00
Chris Smowton
0a4f97b151 Accept changes to standard library types
These are inner classes of the generic class java.lang.invoke.ClassSpecializer, whose generic parameters are no longer inappropriately attributed to its children.
2022-05-10 19:51:12 +01:00
Chris Smowton
997f818643 Accept java-and-kotlin result improvements
This happened because setting the type context for the return-type part of a function's label meant that the label now matches Java <-> Kotlin, and therefore it gets a Kotlin-source source location.
2022-05-10 19:51:12 +01:00
Chris Smowton
ab449e0517 Fix: use void as constructor return types in their labels
Without this we're incompatible with the Java extractor's constructor labelling
2022-05-10 19:51:12 +01:00
Chris Smowton
5188998bc6 Extract outer <-> inner class relationships for generic instances 2022-05-10 19:51:12 +01:00
Chris Smowton
67e3374a23 Fix inner generic type extraction
- Don't attribute type parameters that belong to the outer class to the inner
- Don't extract constructor generic parameters as if they were parameters of the type being instantiated
2022-05-10 19:51:12 +01:00
Tamas Vajk
aa0ddeb29a Fix external type locations in tests 2022-05-10 19:51:12 +01:00
Tamas Vajk
afd71a00d0 Fix extraction of function references without dispatch receiver 2022-05-10 19:51:12 +01:00
Tamas Vajk
ef2795c88b Add ktLocalFunction relation and tests for local and anonymous classes 2022-05-10 19:51:11 +01:00
Tamas Vajk
e0bf7d8246 Extract local class declarations 2022-05-10 19:51:11 +01:00
Tamas Vajk
1e64887903 Extract field receiver in field read/write 2022-05-10 19:51:11 +01:00
Tamas Vajk
10ae157682 Extract function references 2022-05-10 19:51:11 +01:00
Tamas Vajk
6950f868fb Fix type access extraction in field declarations 2022-05-10 19:51:11 +01:00
Tamas Vajk
e5003e4032 Adjust PrintAST query to handle kotlin constructs 2022-05-10 19:51:11 +01:00
Tamas Vajk
73cd497427 Add todo comment to move property from parameter initialization to constructor 2022-05-10 19:51:11 +01:00
Tamas Vajk
313912a131 Fix test expected files 2022-05-10 19:51:11 +01:00
Chris Smowton
2730d07b4c Extract static method qualifier type accesses 2022-05-10 19:51:11 +01:00
Chris Smowton
ef9a213ae1 Cleanup: use extractTypeAccess wherever possible 2022-05-10 19:51:11 +01:00
Chris Smowton
70841a5896 Add test for companion object 2022-05-10 19:51:11 +01:00
Tamas Vajk
30ff5e2517 Change unknown location to whole file location in source extraction 2022-05-10 19:51:11 +01:00
Tamas Vajk
9d7794185e Fix temporary variable locations 2022-05-10 19:51:11 +01:00
Chris Smowton
5c77131637 Add tests for generic methods 2022-05-10 19:51:11 +01:00
Tamas Vajk
67d2c52e86 Extract field declarations 2022-05-10 19:51:11 +01:00
Tamas Vajk
5bc28ab45a Extract externally defined inner classes only once 2022-05-10 19:51:11 +01:00
Chris Smowton
acad36cab4 Implement raw type extraction 2022-05-10 19:51:11 +01:00
Tamas Vajk
6455c988f2 Extract class references 2022-05-10 19:51:11 +01:00
Ian Lynagh
05028e612c Kotlin: Accept test changes 2022-05-10 19:51:11 +01:00
Ian Lynagh
fb90c70e2e Kotlin: Extract visibility for properties 2022-05-10 19:51:11 +01:00
Ian Lynagh
348ae357ed Kotlin: Extract method visibility 2022-05-10 19:51:11 +01:00
Ian Lynagh
6616f452d7 Kotlin: Move extractClassModifiers to KotlinFileExtractor
It doesn't need to be in KotlinUsesExtractor any more, and this gives us
better warnings.
2022-05-10 19:51:11 +01:00
Ian Lynagh
5342b13cb6 Kotlin: Add class modifiers 2022-05-10 19:51:11 +01:00
Ian Lynagh
08bb134022 Java/Kotlin: Tweak consistency queries 2022-05-10 19:51:11 +01:00
Ian Lynagh
7c03ed99dc Java/Kotlin: Add File.is{,Java,Kotlin}SourceFile() 2022-05-10 19:51:10 +01:00
Chris Smowton
70708d69bf Don't extract or call fake-override methods 2022-05-10 19:51:10 +01:00
Chris Smowton
0c7075c749 Give getters and setters their jvm-lowered names 2022-05-10 19:51:10 +01:00
Chris Smowton
248011e828 Improve generics test to indicate callee decltypes 2022-05-10 19:51:10 +01:00
Chris Smowton
26abb4d0e3 Correctly record methods' and constructors' source-declarations 2022-05-10 19:51:10 +01:00
Chris Smowton
2677115385 Switch comment to use Kotlin syntax 2022-05-10 19:51:10 +01:00
Chris Smowton
44c64f0784 Always extract constructor return type as unit 2022-05-10 19:51:10 +01:00
Chris Smowton
d2e626cbee Add declaring type to test to distinguish ambiguously-named methods 2022-05-10 19:51:10 +01:00
Chris Smowton
fa9971c6f3 Uniformly use getFunctionShortName 2022-05-10 19:51:10 +01:00
Chris Smowton
c5e85620e7 Rework conditional generic extraction to use global state 2022-05-10 19:51:10 +01:00
Chris Smowton
25674247a2 Accept test changes relating to generic constructors 2022-05-10 19:51:10 +01:00
Chris Smowton
d57ac71cd0 Anonymous objects: always extract as source classes 2022-05-10 19:51:10 +01:00
Chris Smowton
faa7ccfb01 Add test of selective generic extraction 2022-05-10 19:51:10 +01:00
Chris Smowton
b601cdeb8f Extract generic constructor calls 2022-05-10 19:51:10 +01:00
Chris Smowton
d4519eb1bc Downgrade assert to warning 2022-05-10 19:51:10 +01:00
Chris Smowton
bb3049a686 Extract generic method prototypes
These feature substituted types according to their declaring generic specialisation, with wildcards that reach top-level being converted to their upper or lower bound depending on usage context.

This commit also includes an incidental fix such that constructors declare their return-type as unit, consistent with the Java extractor.
2022-05-10 19:51:10 +01:00
Ian Lynagh
b38f47f9ea Java/Kotlin: Tweak consistency queries 2022-05-10 19:51:10 +01:00
Ian Lynagh
c04912701a Java/Kotlin: Speed up toString.ql
It's less informative now, but manual debugging will likely be needed
to investigate failures.
2022-05-10 19:51:10 +01:00
Ian Lynagh
ab93d166b8 Java/Kotlin: Tweak consistency queries 2022-05-10 19:51:10 +01:00
Tamas Vajk
fa5c3f9159 Remove and replace @anonymousclassdeclstmt with @localtypedeclstmt 2022-05-10 19:51:10 +01:00
Tamas Vajk
e325925f5a Extract field declaration directly inside class 2022-05-10 19:51:10 +01:00
Tamas Vajk
929c50f0b3 Adjust build script based on review 2022-05-10 19:51:10 +01:00
Tamas Vajk
0978e522d0 Fix expected files 2022-05-10 19:51:10 +01:00
Tamas Vajk
7b58d01eff Specify lambda method for big arity lambdas 2022-05-10 19:51:10 +01:00
Tamas Vajk
dec165c5b2 Remove Lambda class as supertype 2022-05-10 19:51:09 +01:00
Tamas Vajk
3cd2583ec8 Handle large arity lambdas, and add missing type access for some constructor calls (needed for anonymous classes) 2022-05-10 19:51:09 +01:00
Tamas Vajk
f4c87cb79d Extract function expressions 2022-05-10 19:51:09 +01:00
Ian Lynagh
b32ac935f6 Revert "Merge pull request #160 from github/smowton/feature/type-substitution-prototypes"
This reverts commit 1dd83a3f0fab407fe94a09fc517c516ed24b1d0c, reversing
changes made to 22aebf8128bfe20bb89e5ecc11e0e8cdd65bf317.
2022-05-10 19:51:09 +01:00
Chris Smowton
4e36b2489c Add test of selective generic extraction 2022-05-10 19:51:09 +01:00
Chris Smowton
b8af2e6e40 Extract generic constructor calls 2022-05-10 19:51:09 +01:00
Chris Smowton
cfb839ac91 Downgrade assert to warning 2022-05-10 19:51:09 +01:00
Chris Smowton
2f8b8fadc3 Extract generic method prototypes
These feature substituted types according to their declaring generic specialisation, with wildcards that reach top-level being converted to their upper or lower bound depending on usage context.

This commit also includes an incidental fix such that constructors declare their return-type as unit, consistent with the Java extractor.
2022-05-10 19:51:09 +01:00
Ian Lynagh
26a0925f99 Kotlin: Add comments saying what generated TRAP files 2022-05-10 19:51:09 +01:00
Ian Lynagh
35ad8f372e Kotlin: Add a test for Kotlin and Java calling each other
Currently kotlin->java causes DB inconsistencies.
2022-05-10 19:51:09 +01:00
Ian Lynagh
1719b921cf Kotlin: Accept test changes 2022-05-10 19:51:09 +01:00
Ian Lynagh
b57d7f5a75 Kotlin: Extract fakeKotlinType for all kt_types
This allows us to make consistent Java+Kotlin databases in the short
term.
2022-05-10 19:51:09 +01:00
Ian Lynagh
40976a91ce Kotlin: Fix a bad label expansion
We were making a key
    @"class;ClassLabelResults(classLabel=java.io.Console, shortName=Console)\$LineReader"
2022-05-10 19:51:09 +01:00
Ian Lynagh
c05aab278a Kotlin: Add a TODO 2022-05-10 19:51:09 +01:00
Ian Lynagh
c35f871c46 Kotlin: Add tests for file classes 2022-05-10 19:51:09 +01:00
Ian Lynagh
43f50888a7 Kotlin: Add a trivial test 2022-05-10 19:51:09 +01:00
Ian Lynagh
c63918d431 Kotlin: Add an empty test 2022-05-10 19:51:09 +01:00
Ian Lynagh
509860b7cf Kotlin: Add a file_classes consistency query 2022-05-10 19:51:09 +01:00
Ian Lynagh
33757a1266 Kotlin: Extract whether a class is a "file" class 2022-05-10 19:51:09 +01:00
Tamas Vajk
fd27243ec6 Add todo comment regarding class declaration stmt 2022-05-10 19:51:09 +01:00
Tamas Vajk
c446b0ecaf Move anonymous class and local function label generation to KotlinUsesExtractor 2022-05-10 19:51:09 +01:00
Tamas Vajk
6dbf278269 Add extension tests 2022-05-10 19:51:08 +01:00
Tamas Vajk
058ff0a60b Remove empty file 2022-05-10 19:51:08 +01:00
Tamas Vajk
2f06c9c03f Fix spacing 2022-05-10 19:51:08 +01:00
Tamas Vajk
05f22576d1 Fix extraction state resetting 2022-05-10 19:51:08 +01:00
Tamas Vajk
ebf91b79a9 Revert moving extraction to SourceFileExtractor 2022-05-10 19:51:08 +01:00
Tamas Vajk
01f46555b0 Fix disappearing variable labels 2022-05-10 19:51:08 +01:00
Tamas Vajk
27f58f2929 Improve code quality 2022-05-10 19:51:08 +01:00
Tamas Vajk
16ba27c476 Extract local functions 2022-05-10 19:51:08 +01:00
Ian Lynagh
f0949a4936 Kotlin: Add a test
This caused a stack overflow on a branch, due to the recursino between
the class and the extension function.
2022-05-10 19:51:08 +01:00
Ian Lynagh
9c4c559ab2 Kotlin: Add some TODO comments 2022-05-10 19:51:08 +01:00
Ian Lynagh
5bc1bdb5a3 Kotlin: Refactor PrimitiveTypeInfo
Avoids mentioning the name of IdSignature.PublicSignature, which used to
be IdSignature.CommonSignature, giving us compatibility issues.
2022-05-10 19:51:08 +01:00
Ian Lynagh
d977500047 Kotlin: Make it easier to diagnose build failures 2022-05-10 19:51:08 +01:00
Ian Lynagh
c525d2a633 Kotlin: Consistently use addClassLabel, and have it handle external classes 2022-05-10 19:51:08 +01:00
Tamas Vajk
161463ecae Fix catch clause location 2022-05-10 19:51:08 +01:00
Tamas Vajk
21af31f3ab CFG changes for non-null operator + some tests 2022-05-10 19:51:08 +01:00
Ian Lynagh
de137415b8 Kotlin: Use an IrClass for the Java class in the priomitive type handling
This means we can add a label for it, and indicate that we use it,
properly.
2022-05-10 19:51:08 +01:00
Chris Smowton
7fa4da8b0c Add explanatory comments 2022-05-10 19:51:08 +01:00
Chris Smowton
7d62f1d2de Update test expectations 2022-05-10 19:51:08 +01:00
Chris Smowton
8accd35ce8 Substitute in generic type arguments when extracting the supertypes of an instantiated type 2022-05-10 19:51:08 +01:00
Ian Lynagh
2dcd49c6a5 Kotlin: Build the appropriate single version, rather than always 1.5 2022-05-10 19:51:08 +01:00
Tamas Vajk
abc0da3e60 Extract extension method receivers as parameters 2022-05-10 19:51:08 +01:00
Tamás Vajk
04daa7f28f Revert "Kotlin: Fix extraction of dispatch and extension receivers" 2022-05-10 19:51:08 +01:00
Ian Lynagh
cd84a6a5b6 Kotlin: Avoid external locations appearing in type_equivalences test 2022-05-10 19:51:08 +01:00
Tamas Vajk
a4275865da Fix location of variable access in LHS of assignment 2022-05-10 19:51:07 +01:00
Ian Lynagh
40e4c93615 Kotlin: TODO() now works 2022-05-10 19:51:07 +01:00
Ian Lynagh
669fe616dd Kotlin: Renumber lines in expressions test 2022-05-10 19:51:07 +01:00
Ian Lynagh
50400bf7af Kotlin: Add TODO() to test; doesn't work yet 2022-05-10 19:51:07 +01:00
Ian Lynagh
2b483597f8 Kotlin: Ranges already work
We might want to extract a sugared form of them in the future, but for
now this works.
2022-05-10 19:51:07 +01:00
Ian Lynagh
1abaecf158 Kotlin: String templates are already supported 2022-05-10 19:51:07 +01:00
Ian Lynagh
4c8a87bfb1 Kotlin: Accept test changes 2022-05-10 19:51:07 +01:00
Ian Lynagh
0b3754c932 Kotlin: Fix handling Unit in various places 2022-05-10 19:51:07 +01:00
Ian Lynagh
ec827d2f0a Kotlin: Add ability to give more type contexts 2022-05-10 19:51:07 +01:00
Ian Lynagh
6c1439c180 Kotlin: Add a test for type equivalences 2022-05-10 19:51:07 +01:00
Ian Lynagh
606b36e21f Kotlin: Accept test changes 2022-05-10 19:51:07 +01:00
Ian Lynagh
7ca6da1d13 Kotlin/Java: children consistency query: extension receiver is now a gap 2022-05-10 19:51:07 +01:00
Ian Lynagh
75e22da096 Kotlin: Fix extraction of dispatch and extension receivers
It is possible for a call to have both, e.g. the `arg.ext()` call in:

class Class1 {
    val y = 4
}
class Class2 (val arg:Class1) {
    val x = 3
    fun someFun() {
        arg.ext();
    }
    fun Class1.ext() {
        val z = x + y
    }
}
2022-05-10 19:51:07 +01:00
Ian Lynagh
76d7ac9898 Kotlin: Accept test changes 2022-05-10 19:51:07 +01:00
Ian Lynagh
6a16588484 Kotlin: Allow comments on enum entries 2022-05-10 19:51:07 +01:00
Ian Lynagh
cc478eb6ee Kotlin: Add comments on enum test 2022-05-10 19:51:07 +01:00
Ian Lynagh
03199091cd Kotlin: Add SAFE_CAST support 2022-05-10 19:51:07 +01:00
Ian Lynagh
1c5f6d70bc Kotlin: Accept changes 2022-05-10 19:51:07 +01:00
Ian Lynagh
25ccf0569e Kotlin: ReturnStmt CFG isn't handled properly yet 2022-05-10 19:51:07 +01:00
Ian Lynagh
db7f5a04be Kotlin: BreakStmt CFG isn't handled properly yet 2022-05-10 19:51:07 +01:00
Ian Lynagh
712d70248a Kotlin: Add CFG for VarArgExpr 2022-05-10 19:51:07 +01:00
Ian Lynagh
8440bafc42 Kotlin: Add CFG for KtAnonymousClassDeclarationStmt 2022-05-10 19:51:07 +01:00
Ian Lynagh
5ae74949a0 Kotlin: Add CFG for ClassExpr 2022-05-10 19:51:07 +01:00
Ian Lynagh
2135a870d3 Kotlin: Fix CFG for StmtExpr 2022-05-10 19:51:06 +01:00
Ian Lynagh
2e5cf92f8a Kotlin: Fix CFG for string templates 2022-05-10 19:51:06 +01:00
Ian Lynagh
fcbe4331b4 Kotlin/Java: Add a (currently rather lax) cfgDeadEnds consistency query 2022-05-10 19:51:06 +01:00
Tamas Vajk
874afa7fd7 Fix missing extension receiver extraction 2022-05-10 19:51:06 +01:00
Tamas Vajk
23c5caadc8 Fix String?.plus extraction 2022-05-10 19:51:06 +01:00
Tamas Vajk
ea4e919af5 Extract missing functions directly in kotlin package 2022-05-10 19:51:06 +01:00
Tamas Vajk
3a2f7bec1c Fix test expected files 2022-05-10 19:51:06 +01:00
Tamas Vajk
6246b2142c Add enclosing stmt to arrayOf extraction 2022-05-10 19:51:06 +01:00
Tamas Vajk
8de5e39309 Extract arrayOf-like calls 2022-05-10 19:51:06 +01:00
Tamas Vajk
8b81ee7e59 Add array creation tests 2022-05-10 19:51:06 +01:00
Chris Smowton
64e1367e59 Make standard library locations consistent between Java and Kotlin 2022-05-10 19:51:06 +01:00
Ian Lynagh
547b60d68f Kotlin: Add paramTypes test 2022-05-10 19:51:06 +01:00
Ian Lynagh
d5b4931b7f Kotlin: Tweak superTypes test to give better locations 2022-05-10 19:51:06 +01:00
Ian Lynagh
50c2d10777 Kotlin: Improve the supertypes test
Note the line
        | file://<external>/superChain.kt:2:1:2:60 | SuperChain2<T5,String> | file://<external>/superChain.kt:1:1:1:33 | SuperChain1<T3,String> |
is currently wrong; the supertype of SuperChain2<T5,String> should be
SuperChain1<T5,String>.
2022-05-10 19:51:06 +01:00
Ian Lynagh
c05aa7bb68 Kotlin: Add superChain test 2022-05-10 19:51:06 +01:00
Ian Lynagh
b876ee98e5 Kotlin: Tweak the superTypes test 2022-05-10 19:51:06 +01:00
Ian Lynagh
90d7c2b3ce Java/Kotlin: Add a statementEnclosingExpr consistency test 2022-05-10 19:51:06 +01:00
Ian Lynagh
7baefbb9e5 Kotlin: Add WhenBranch.getWhenExpr() 2022-05-10 19:51:06 +01:00
Ian Lynagh
46f103c243 Kotlin: Accept test changes 2022-05-10 19:51:06 +01:00
Ian Lynagh
5c2ce95b1a Kotlin: Populate statementEnclosingExpr 2022-05-10 19:51:06 +01:00
Ian Lynagh
2b973fa3b1 Kotlin: Add support for IrSyntheticBody
I'm not sure it's worth adding an entity to the database for them,
although that would allow us to use a 'case' in the dbscheme for
the different kinds.

There's no QLL support for this info yet.
2022-05-10 19:51:06 +01:00
Tamas Vajk
4ca024f043 Fix try statement extraction 2022-05-10 19:51:06 +01:00
Tamas Vajk
716b87d200 Extract not-null expression 2022-05-10 19:51:06 +01:00
Ian Lynagh
6603767d94 Kotlin: Clarify !/ paths 2022-05-10 19:51:06 +01:00
Ian Lynagh
f40ab39447 Kotlin: Small fixes and a little more documentation for TrapWriter 2022-05-10 19:51:06 +01:00
Ian Lynagh
d1fefe0246 Kotlin: Refactor TrapWriters
Now ClassFileTrapWriter is just FileTrapWriter, which no longer takes a
nullable IrFileEntry.

SourceFileTrapWriter still extends FileTrapWriter, and adds the
IrFileEntry, allowing it to override the location functions with more
useful variants.

populateFileTables no longer has a default. I think that for the sake
of a handful of calls, it's simpler to be explicit so we aren't
confused.
2022-05-10 19:51:05 +01:00
Ian Lynagh
1990b68c21 Kotlin: Return more precise types from PopulateFile.java 2022-05-10 19:51:05 +01:00
Ian Lynagh
83ac77dccc Kotlin: Start documenting TrapWriter 2022-05-10 19:51:05 +01:00
Tamas Vajk
afabe652c1 Add anonymous class declaration stmt 2022-05-10 19:51:05 +01:00
Ian Lynagh
3e9d12aff0 Kotlin: Accept test changes 2022-05-10 19:51:05 +01:00
Ian Lynagh
37d6bc29dc Kotlin: Fix Byte tests 2022-05-10 19:51:05 +01:00
Ian Lynagh
1eda692ec8 Kotlin: Import org.jetbrains.kotlin.ir.util.* in KotlinFileExtractor
This makes dump() available
2022-05-10 19:51:05 +01:00
Ian Lynagh
2d8a2abe5c Kotlin: Recognise more numeric types 2022-05-10 19:51:05 +01:00
Ian Lynagh
76151b413f Kotlin: Add more Long tests 2022-05-10 19:51:05 +01:00
Ian Lynagh
6b5fe14e94 Kotlin: Add tesets for more integer types 2022-05-10 19:51:05 +01:00
Ian Lynagh
1b40f78b9c Kotlin: Recognise + etc for Double 2022-05-10 19:51:05 +01:00
Ian Lynagh
5b5a6042a9 Kotlin: Add tests for more Double operators 2022-05-10 19:51:05 +01:00
Chris Smowton
35e6b06fe3 Revert "Fix failing tests"
This reverts commit 940db3d0828422bc26d7167c138199aa51ab4e89.
2022-05-10 19:51:05 +01:00
Chris Smowton
bb7a17b5bd Add missing test file 2022-05-10 19:51:05 +01:00
Ian Lynagh
f447d40740 Kotlin: Temporary consistency query tweak to get the tests passing 2022-05-10 19:51:05 +01:00
Tamas Vajk
ae86fcb499 Split main extractor file 2022-05-10 19:51:05 +01:00
Tamas Vajk
2dfe50cbaa Change constructor and type name of anonymous classes to empty string 2022-05-10 19:51:05 +01:00
Tamas Vajk
b7faa33c60 Fix constructor call type access 2022-05-10 19:51:05 +01:00
Tamas Vajk
b7e0828f78 Extract anonymous object creation 2022-05-10 19:51:05 +01:00
Tamas Vajk
ab6b500475 Fix failing tests 2022-05-10 19:51:05 +01:00
Ian Lynagh
10004c77d1 Kotlin: some TODO stuff works now 2022-05-10 19:51:05 +01:00
Ian Lynagh
a3e70fdb5c Kotlin: Add support for ieee754equals 2022-05-10 19:51:05 +01:00
Ian Lynagh
78d2ef52c1 Kotlin: Towards better equality checking 2022-05-10 19:51:05 +01:00
Ian Lynagh
5da15ca03b Kotlin: Resugar != 2022-05-10 19:51:04 +01:00
Ian Lynagh
b4c3f57bab Kotlin: Get != working again 2022-05-10 19:51:04 +01:00
Chris Smowton
956c479db3 Document TypeResult 2022-05-10 19:51:04 +01:00
Chris Smowton
ccf21b7183 Implement Java signature extraction 2022-05-10 19:51:04 +01:00
Chris Smowton
6391484692 Add modifiers to array built-in functions 2022-05-10 19:51:04 +01:00
Chris Smowton
b33f2d9952 Merge shortName recursion into useType 2022-05-10 19:51:04 +01:00
Ian Lynagh
36dae240df Kotlin: Allow building only a single way 2022-05-10 19:51:04 +01:00
Ian Lynagh
0ce6e53386 Kotlin: Remove unused expressions and fix a copy/paste-o 2022-05-10 19:51:04 +01:00
Tamas Vajk
da0e2c276f Add comment explaining why the annotation is needed 2022-05-10 19:51:04 +01:00
Tamas Vajk
cb406619cb Reintroduce sealed interfaces for generated DB types 2022-05-10 19:51:04 +01:00
Tamas Vajk
c4ad2f3463 Add kotlin 1.4 support 2022-05-10 19:51:04 +01:00
Tamas Vajk
3939a2a47c Change build script to build multiple versions of the plugin 2022-05-10 19:51:04 +01:00
Ian Lynagh
22c87b20cc Kotlin: Add an exception for a consistency check 2022-05-10 19:51:04 +01:00
Ian Lynagh
be5e478718 Kotlin: Accept test change 2022-05-10 19:51:04 +01:00
Ian Lynagh
744f3db68d Kotlin: Handle binops correctly 2022-05-10 19:51:04 +01:00
Ian Lynagh
d63ef23bda Kotlin: Remove an out-of-date consistency exception 2022-05-10 19:51:04 +01:00
Ian Lynagh
755bf4d8b3 Java/Kotlin: Add 'children' consistency query 2022-05-10 19:51:04 +01:00
Ian Lynagh
8f1f137fa1 Java/Kotlin: Add UnaryExpr consistency query 2022-05-10 19:51:04 +01:00
Ian Lynagh
90365c9c58 Java/Kotlin: Add a consistency query for BinaryExpr 2022-05-10 19:51:04 +01:00
Ian Lynagh
9e2a3a9da8 Java/Kotlin: Add a consistency query for blocks 2022-05-10 19:51:04 +01:00
Tamas Vajk
ab86778e1d Remove external property related log messages 2022-05-10 19:51:04 +01:00
Chris Smowton
5ee9135643 Couple more style fixes 2022-05-10 19:51:04 +01:00
Chris Smowton
970e3d64c0 Fix various style warnings highlighted by IntelliJ 2022-05-10 19:51:04 +01:00
Chris Smowton
8f5bbc7bd8 superTypes test: restore location info without full paths 2022-05-10 19:51:03 +01:00
Chris Smowton
87d6313278 Move extractClassInstance to the file extractor
Since now we know the file context has been set correctly at this point
2022-05-10 19:51:03 +01:00
Chris Smowton
c4d6321e60 Fix whitespace 2022-05-10 19:51:03 +01:00
Chris Smowton
fcab0474c9 Amend call.ql to avoid external source locations and accept changes 2022-05-10 19:51:03 +01:00
Chris Smowton
2bcc3d425e Amend a test to avoid external paths and accept changes 2022-05-10 19:51:03 +01:00
Chris Smowton
87b04bc22b Add test for expected filenames 2022-05-10 19:51:03 +01:00
Chris Smowton
5ec546bcb0 Extract locations for generic instantiations 2022-05-10 19:51:03 +01:00
Chris Smowton
f06285e9c7 Fix: use source information for class actually extracted in case of K<->J substitution 2022-05-10 19:51:03 +01:00
Chris Smowton
bde4534050 Only report locations without a source offset in non-source files
Also adjust tests that would otherwise report types with locations outside the source tree (i.e., for the most part in the standard library)
2022-05-10 19:51:03 +01:00
Chris Smowton
c2fef58b21 Extract source files for external types 2022-05-10 19:51:03 +01:00
Tamas Vajk
4c5b4b15a9 Allow associating comments with fields 2022-05-10 19:51:03 +01:00
Tamas Vajk
097d87604f Add test case to cover comments on properties 2022-05-10 19:51:03 +01:00
Tamas Vajk
d0c470dbac Add direct field access support 2022-05-10 19:51:03 +01:00
Ian Lynagh
b741dea100 Kotlin: Accept test changes 2022-05-10 19:51:03 +01:00
Ian Lynagh
3a0435b196 Kotlin: Towards 'this' qualifiers
This probably handles most cases well enough
2022-05-10 19:51:03 +01:00
Ian Lynagh
9158f0192b Kotlin: Enhance 'this' test 2022-05-10 19:51:03 +01:00
Ian Lynagh
2320553723 Kotlin: Add tests for this 2022-05-10 19:51:03 +01:00
Ian Lynagh
87e8425603 Kotlin: Extract the abstractness of classes. 2022-05-10 19:51:03 +01:00
Ian Lynagh
45658e5d89 Kotlin: Add writeCallableEnclosingExpr calls 2022-05-10 19:51:03 +01:00
Ian Lynagh
854a03d696 Kotlin: Fix property initialisers 2022-05-10 19:51:03 +01:00
Ian Lynagh
aefe5c5c58 Kotlin: Accept test changes 2022-05-10 19:51:03 +01:00
Ian Lynagh
e6e56238c5 Kotlin: Handle properties better 2022-05-10 19:51:03 +01:00
Chris Smowton
44bf35e623 Add and update tests 2022-05-10 19:51:03 +01:00
Chris Smowton
1b7e33b6e3 Remove Kotlin element and component type from arrays
Now that these are no longer required, array extraction can extract kt-types consistently with other parameterised classes.
2022-05-10 19:51:03 +01:00
Chris Smowton
70294bd26b Array types: distinguish (e.g.) Array<Int> from IntArray 2022-05-10 19:51:03 +01:00
Chris Smowton
380da465b9 Fix bad rebase 2022-05-10 19:51:02 +01:00
Chris Smowton
b4138838fe Update TODOs 2022-05-10 19:51:02 +01:00
Chris Smowton
329ead2b52 Pull out and tidy array extraction 2022-05-10 19:51:02 +01:00
Ian Lynagh
e947e6234e Kotlin: Use 2G when compiling
For me, kotlinc default to 256M, which isn't enough when we are
extracting.
2022-05-10 19:51:02 +01:00
Ian Lynagh
2625c101ad Kotlin: Show class name in log messages 2022-05-10 19:51:02 +01:00
Ian Lynagh
0bf60fff53 Kotlin: Add a test that was failing dbcheck, and comment out the cause 2022-05-10 19:51:02 +01:00
Ian Lynagh
8fc75abc6c Kotlin: Accept test changes 2022-05-10 19:51:02 +01:00
Ian Lynagh
e1cfaaaa9a Kotlin: Extract listOf(...) 2022-05-10 19:51:02 +01:00
Chris Smowton
3c7fb94002 Update test expectations 2022-05-10 19:51:02 +01:00
Chris Smowton
06c4fd9060 Properly extract wildcard bounds 2022-05-10 19:51:02 +01:00
Tamas Vajk
356639dadd Add optional exitProcess after extraction 2022-05-10 19:51:02 +01:00
Tamas Vajk
69e8db06cb Add optional compilation start plugin option + remove exitProcess 2022-05-10 19:51:02 +01:00
Chris Smowton
6fb5854589 Array types: record dimensionality 2022-05-10 19:51:02 +01:00
Chris Smowton
239ee588a6 Update test expectations 2022-05-10 19:51:02 +01:00
Chris Smowton
805b54897e KotlinType: accept non-class-or-interface Java types 2022-05-10 19:51:02 +01:00
Chris Smowton
1d95431a7a Always use the nullable type for arrays 2022-05-10 19:51:02 +01:00
Chris Smowton
0ba4753b8f Restrict Kotlin types describing arrays
* Always use a nullable type
* Never use a type projection (same behaviour as IrType.getArrayElementType)

Otherwise the kotlin type doesn't functionally depend on the type label
2022-05-10 19:51:02 +01:00
Chris Smowton
a6dc408c4e Fix: bracket string template expression properly 2022-05-10 19:51:02 +01:00
Chris Smowton
8016aa7027 Adapt to refactor; useType changes 2022-05-10 19:51:02 +01:00
Chris Smowton
660988d8ac Ensure Unit type is extracted when needed 2022-05-10 19:51:02 +01:00
Chris Smowton
efe3a77efe shortName: use boxed types for type arguments and use K->J class substitutions 2022-05-10 19:51:02 +01:00
Chris Smowton
16335b126f Include type parameters in class short names 2022-05-10 19:51:02 +01:00
Chris Smowton
8acf7d74c1 Restore check for Array<T> type argument 2022-05-10 19:51:02 +01:00
Chris Smowton
dd3bb053e5 Add extracted array length and clone members 2022-05-10 19:51:02 +01:00
Chris Smowton
d62af44baa Extract array type inheritence graph 2022-05-10 19:51:02 +01:00
Chris Smowton
23553f15ee Arrays: extract dimensionality 2022-05-10 19:51:01 +01:00
Chris Smowton
c571657fb1 Abbreviate array test 2022-05-10 19:51:01 +01:00
Chris Smowton
f1a3c9ca20 Arrays: note TODOs 2022-05-10 19:51:01 +01:00
Chris Smowton
2cc5f3e5b7 kt_*_types tables: cite correct Kotlin classid for arrays 2022-05-10 19:51:01 +01:00
Chris Smowton
b926521e7a Only write arrays table on first usage 2022-05-10 19:51:01 +01:00
Chris Smowton
055e9b7797 Convert primitive arrays to Java arrays 2022-05-10 19:51:01 +01:00
Chris Smowton
a92e20e526 Extract nullable arrays as Java arrays
Nullability doesn't matter to this conversion since Java's arrays are reftypes
2022-05-10 19:51:01 +01:00
Ian Lynagh
80e2140ca7 Kotlin: Add TrapWriter.writeComment 2022-05-10 19:51:01 +01:00
Ian Lynagh
5cf14e6f39 Kotlin: Tweak a comment 2022-05-10 19:51:01 +01:00
Ian Lynagh
8853489f04 Kotlin: Add a "generted by" field to the diagnostics table 2022-05-10 19:51:01 +01:00
Ian Lynagh
512e4ce41e Kotlin: Fix bug in DB scheme generator 2022-05-10 19:51:01 +01:00
Ian Lynagh
be75d30ee0 Kotlin: Add support for varargs 2022-05-10 19:51:01 +01:00
Ian Lynagh
497263e92d Kotlin: Accept test changes 2022-05-10 19:51:01 +01:00
Ian Lynagh
bdaa3ce2b3 Kotlin: Add support for companion objects 2022-05-10 19:51:01 +01:00
Ian Lynagh
f726e6acf8 Kotlin: Fix handling of objects in external dependencies 2022-05-10 19:51:01 +01:00
Ian Lynagh
b460c92c61 Kotlin: Add modifiers to object INSTANCEs 2022-05-10 19:51:01 +01:00
Ian Lynagh
112fac6286 Kotlin: We only support non-companion objects for now 2022-05-10 19:51:01 +01:00
Ian Lynagh
e5cd32bdfe Kotlin: Get the tests passing again 2022-05-10 19:51:01 +01:00
Ian Lynagh
ceb1e57ddd Kotlin: Add support for objects 2022-05-10 19:51:01 +01:00
Tamás Vajk
35a15d7eb4 Fix typo 2022-05-10 19:51:01 +01:00
Ian Lynagh
cb1124b5ff Kotlin: Add a test for type aliases 2022-05-10 19:51:01 +01:00
Ian Lynagh
87b433142c Kotlin: Add support for Kotlin type aliases 2022-05-10 19:51:01 +01:00
Ian Lynagh
8330a404df Kotlin: Add warning location to warnings
This also tweaks how the "too many warnings" logic works
2022-05-10 19:51:01 +01:00
Ian Lynagh
41d4c21910 Kotlin: Add a warning 2022-05-10 19:51:01 +01:00
Ian Lynagh
2d43e7b2d1 Kotlin: Speed up getAPrimaryQlClass
It now gives less useful info, but can be manually investigated if it
fails.
2022-05-10 19:51:00 +01:00
Ian Lynagh
59307285e8 Kotlin: Speed up the toString consistency query
Using Top.getAQlClass() means we have to evaluate
SummarizedCallableExternal's charpred, and hence summaryElement,
which is slow.
2022-05-10 19:51:00 +01:00
Ian Lynagh
9a621479cc Kotlin: accept test changes 2022-05-10 19:51:00 +01:00
Ian Lynagh
9b3f36d1ae Kotlin: Remove useTypeOld 2022-05-10 19:51:00 +01:00
Ian Lynagh
e61ff60bf8 Kotlin: Add KotlinType to ExtensionMethod 2022-05-10 19:51:00 +01:00
Ian Lynagh
6cf0b755f0 Kotlin: Add KotlinType to localvars 2022-05-10 19:51:00 +01:00
Ian Lynagh
06a41b3923 Kotlin: Add KotlinTypes to arrays 2022-05-10 19:51:00 +01:00
Ian Lynagh
ba56517900 Kotlin: Add Variable.getKotlinType() 2022-05-10 19:51:00 +01:00
Ian Lynagh
ef22194eed Kotlin: Add KotlinType to params 2022-05-10 19:51:00 +01:00
Ian Lynagh
0d5e471b96 Kotlin: Give methods and constructors a KotlinType 2022-05-10 19:51:00 +01:00
Ian Lynagh
d9822266f5 Kotlin: Fix SafeCastConversionContext QLL 2022-05-10 19:51:00 +01:00
Ian Lynagh
c20ee76826 Kotlin: Give fields a Kotlin type
This meant refactoring the EnumEntry extraction a bit. The IR doesn't
give us a type for fields, so we have to make it up based on the parent.
2022-05-10 19:51:00 +01:00
Ian Lynagh
e120059a18 Kotlin: Accept test changes 2022-05-10 19:51:00 +01:00
Ian Lynagh
b3a28af319 Kotlin: Move extractTypeParameter back to KotlinFileExtractor 2022-05-10 19:51:00 +01:00
Ian Lynagh
118d630125 Kotlin: Add a test for instances 2022-05-10 19:51:00 +01:00
Ian Lynagh
7421e95816 Kotlin: Pull more out into KotlinUsesExtractor 2022-05-10 19:51:00 +01:00
Ian Lynagh
db0360d211 Kotlin: Accept test changes 2022-05-10 19:51:00 +01:00
Ian Lynagh
b381556a06 Kotlin: Fix up things that got pulled out into KotlinUsesExtractor 2022-05-10 19:51:00 +01:00
Ian Lynagh
a5a42b4416 Kotlin: Refactor so that we can't give locations to "used" things
Things we use may not be in the same file as us, so we aren't able to
generate valid locations for them.
2022-05-10 19:51:00 +01:00
Ian Lynagh
960c436824 Kotlin: Call extractClassCommon later
This fixes a "Missing type parameter label" warning from the extractor
with
    interface Foo<T>
    class Bar<T>: Foo<T> { }
caused by the `: Foo<T>` being extracted before extracting the `T`
in `Bar<T>`.
2022-05-10 19:51:00 +01:00
Ian Lynagh
6c957284de Kotlin: Add support for enum value accesses 2022-05-10 19:51:00 +01:00
Ian Lynagh
d565a16fe6 Kotlin: Add enums to expr test 2022-05-10 19:51:00 +01:00
Ian Lynagh
84b53ba9cf Kotlin: Accept test changes 2022-05-10 19:51:00 +01:00
Ian Lynagh
976cc31c7a Kotlin: Add support for string templates 2022-05-10 19:50:59 +01:00
Ian Lynagh
168786ae71 Kotlin: Add string concatenations to exprs test 2022-05-10 19:50:59 +01:00
Ian Lynagh
81fd7c735a Kotlin: Add suport for enum classes 2022-05-10 19:50:59 +01:00
Ian Lynagh
2b01c5d825 Kotlin: Follow changes in main 2022-05-10 19:50:59 +01:00
Ian Lynagh
9996d77701 Kotlin: Reinstate disabled test now bug is fixed 2022-05-10 19:50:59 +01:00
Chris Smowton
97f380eddc Don't abort external class extraction after first duplicate 2022-05-10 19:50:59 +01:00
Ian Lynagh
5bb9357dbe Kotlin: Disable part of a test that gives us DB check inconsistencies 2022-05-10 19:50:59 +01:00
Ian Lynagh
e8fd9ed948 Kotlin: Add a warning suppression 2022-05-10 19:50:59 +01:00
Ian Lynagh
cbd265ab7a Kotlin: Add support for try statements 2022-05-10 19:50:59 +01:00
Ian Lynagh
6b5663df46 Kotlin: Handle Short and Byte literals
I don't think we need separate DB types for them
2022-05-10 19:50:59 +01:00
Ian Lynagh
f0ac63c466 Kotlin: Extend expressions test 2022-05-10 19:50:59 +01:00
Ian Lynagh
49d2e86b5e Kotlin: Accept test changes 2022-05-10 19:50:59 +01:00
Ian Lynagh
ba335b0c69 Kotlin: Add StmtExpr
In some contexts, Kotlin has what we would call a Stmt inside what we
would call an Expr. This allows us to handle this case.
2022-05-10 19:50:59 +01:00
Ian Lynagh
2ba8ccafa9 Kotlin: Make build compatible with older javac's 2022-05-10 19:50:59 +01:00
Ian Lynagh
6fd8d638a3 Kotlin: Accept test output 2022-05-10 19:50:59 +01:00
Ian Lynagh
9a886260cd Kotlin: Add support for IMPLICIT_COERCION_TO_UNIT 2022-05-10 19:50:59 +01:00
Ian Lynagh
924c615216 Kotlin: Enhance exprs test 2022-05-10 19:50:59 +01:00
Ian Lynagh
46e55f5990 Kotlin: Add support for IMPLICIT_NOTNULL 2022-05-10 19:50:59 +01:00
Ian Lynagh
d181b4b9cc Kotlin: Enhance the exprs test 2022-05-10 19:50:59 +01:00
Chris Smowton
dfa9bef5bd Fix gradle homedir search 2022-05-10 19:50:59 +01:00
Ian Lynagh
a6c504abe3 Kotlin: Add support for implicit casts 2022-05-10 19:50:59 +01:00
Ian Lynagh
62b3e07ae6 Kotlin: Accept test changes 2022-05-10 19:50:58 +01:00
Ian Lynagh
ba7a7535e9 Kotlin: Add support for more type operators 2022-05-10 19:50:58 +01:00
Ian Lynagh
d247e4fcff Kotlin: WhenBranch isn't postorder 2022-05-10 19:50:58 +01:00
Ian Lynagh
c4880cc935 Kotlin: Fix handling of non-true conditions 2022-05-10 19:50:58 +01:00
Ian Lynagh
b9d6712371 Kotlin: Update test output 2022-05-10 19:50:58 +01:00
Ian Lynagh
7f3ae94d73 Tweak the WhenExpr CFG and QL class 2022-05-10 19:50:58 +01:00
Ian Lynagh
f95934a0c5 Kotlin: Use trace (silently for now) rather than info for writing TRAP files
The on-demand "Writing trap file for: " messages are drowning out
everything else while running the tests.
2022-05-10 19:50:58 +01:00
Ian Lynagh
d6692e434a Kotlin: Add support for "is" ("instanceof") 2022-05-10 19:50:58 +01:00
Ian Lynagh
d05643fa88 Kotlin: Add library-tests/controlflow/paths test (copied from Java) 2022-05-10 19:50:58 +01:00
Ian Lynagh
e755cc92b6 Kotlin: Add controlflow/dominance test (copied from Java) 2022-05-10 19:50:58 +01:00
Ian Lynagh
aebd8edf85 Kotlin: Make library-tests/controlflow/basic quieter 2022-05-10 19:50:58 +01:00
Ian Lynagh
d0bf462a45 Kotlin: Add a copy of Java's controlflow/basic test 2022-05-10 19:50:58 +01:00
Ian Lynagh
715a92c602 Kotlin: Add CFG for when expressions 2022-05-10 19:50:58 +01:00
Chris Smowton
070c0a03f4 Add .fromSource() qualifier to tests 2022-05-10 19:50:58 +01:00
Chris Smowton
3cb68bd7be kotlin-extractor build: include Java source files 2022-05-10 19:50:58 +01:00
Chris Smowton
124dcb0e5f Update test expectations 2022-05-10 19:50:58 +01:00
Chris Smowton
4dda475a8d Fix source location column numbers 2022-05-10 19:50:58 +01:00
Chris Smowton
e65f451af6 erase: retain question-mark qualifier if present 2022-05-10 19:50:58 +01:00
Chris Smowton
48d5561c95 Use getClassLabel for Kotlin <-> Java type correspondences
Without this, the table can be non-functional due to mapping one unqualified Kotlin type onto several qualified Java types
2022-05-10 19:50:58 +01:00
Chris Smowton
f5021e8e68 Java: produce Java 8 class files for compatibility with packaged Java 11 binary 2022-05-10 19:50:58 +01:00
Chris Smowton
e5e694f7d3 Adjust Kotlin type correspondence tables when extracting a substituted type 2022-05-10 19:50:58 +01:00
Chris Smowton
12ce2d5829 Substitute Kotlin classes for Java equivalents 2022-05-10 19:50:58 +01:00
Chris Smowton
6de5a36cdc Write Java class files in gzip format
This means our names match those expected by javac
2022-05-10 19:50:58 +01:00
Chris Smowton
4a18705d73 Write .set file for source file 2022-05-10 19:50:58 +01:00
Chris Smowton
b299779750 Create Files table entries for JAR/JRT files 2022-05-10 19:50:58 +01:00
Chris Smowton
8e63d10c1f Populate Folders, containerparent tables 2022-05-10 19:50:57 +01:00
Chris Smowton
4c3b9e658b Fix trap file output paths
These should be named for the class name, not its fs location
2022-05-10 19:50:57 +01:00
Chris Smowton
debb942c0e Implement mtime and class version extraction 2022-05-10 19:50:57 +01:00
Chris Smowton
a0671cafb1 Remove trap file compression for now 2022-05-10 19:50:57 +01:00
Chris Smowton
2cc003ff0e External class extraction prototype 2022-05-10 19:50:57 +01:00
Mathias Vorreiter Pedersen
a7fe37a631 Merge pull request #9047 from geoffw0/xxe6
C++: Add support for SAX2XMLReader in the CWE-611 XXE query.
2022-05-10 19:07:35 +01:00
Tamas Vajk
e9b249855b Add gitignore to kotlin-explorer 2022-05-10 18:46:02 +01:00
Tamas Vajk
b7b506a23d Improve temp directory cleanup 2022-05-10 18:46:02 +01:00
Tamas Vajk
52341dc99f Modify build script to build both standalone and embeddable plugin variant 2022-05-10 18:46:02 +01:00
Ian Lynagh
f458745eff Kotlin: Update tests 2022-05-10 18:46:02 +01:00
Ian Lynagh
286e29cd81 Kotlin: Add exprstmt's where appropriate 2022-05-10 18:46:02 +01:00
Ian Lynagh
8704536f35 Kotlin: local variable indexes start from 1 2022-05-10 18:46:02 +01:00
Ian Lynagh
b3d459d122 Kotlin: Accept test changes 2022-05-10 18:46:02 +01:00
Ian Lynagh
8df5abaef9 Kotlin: Add localvariabledeclstmt 2022-05-10 18:46:02 +01:00
Ian Lynagh
e5e6225d57 Kotlin: Add a build.py script that uses kotlinc to build 2022-05-10 18:46:02 +01:00
Ian Lynagh
1d1b9fe805 Kotlin: Add support for more kind of literal
And a test
2022-05-10 18:46:02 +01:00
Tamas Vajk
731d601cdd Add optional dbscheme path parameter to KotlinExtractorDbScheme.kt generator 2022-05-10 18:46:02 +01:00
Tamas Vajk
48b388daf7 Remove version number from output artifact name 2022-05-10 18:46:02 +01:00
Tamas Vajk
ab102245da Add codeql-kotlin to the CODEOWNERS file 2022-05-10 18:46:01 +01:00
Ian Lynagh
14a10564f3 Kotlin: Fix File locations, and fromSource/hasSourceLocation for Kotlin code 2022-05-10 18:46:01 +01:00
Ian Lynagh
b9359bd119 Kotlin: Add a test case to be added
Found by Tamás
2022-05-10 18:46:01 +01:00
Ian Lynagh
cd41d5b9cf Kotlin: Add KotlinType to exprs 2022-05-10 18:46:01 +01:00
Ian Lynagh
63e96dffea Kotlin: Add a testcase as a comment for now, so we don't lose it 2022-05-10 18:46:01 +01:00
Ian Lynagh
45cade8ff8 Kotlin: Accept/update tests 2022-05-10 18:46:01 +01:00
Ian Lynagh
1bce9a131a Kotlin: Towards KotlinType support 2022-05-10 18:46:01 +01:00
Ian Lynagh
ca96d55476 Typo 2022-05-10 18:46:01 +01:00
Ian Lynagh
636e15f422 Kotlin: Split extractClass into extractClassSource, extractClassInstance 2022-05-10 18:46:01 +01:00
Ian Lynagh
9eadbea5cd Kotlin: Split useClass into useClassSource and useClassInstance 2022-05-10 18:46:01 +01:00
Ian Lynagh
490e803098 Kotlin: Be more specific about function parents 2022-05-10 18:46:01 +01:00
Tamas Vajk
6f3ae8da47 Improve todo comment 2022-05-10 18:46:01 +01:00
Tamas Vajk
ec889f933f Remove unneeded extraction warning 2022-05-10 18:46:01 +01:00
Tamas Vajk
1a6d693618 Implement review findings + fix ID of nested types 2022-05-10 18:46:00 +01:00
Tamas Vajk
85e713fa31 Extract generic type parameters as reference types even for primitive Kotlin types + add simplified array extraction 2022-05-10 18:46:00 +01:00
Tamas Vajk
b542769fe9 Fix constructor extraction and extract type arguments of constructor calls 2022-05-10 18:46:00 +01:00
Tamas Vajk
936c29b70c Handle star type argument 2022-05-10 18:46:00 +01:00
Tamas Vajk
8dff527a0e WIP: type arg extraction 2022-05-10 18:46:00 +01:00
Tamas Vajk
0c6e20928c Kotlin: extract type parameters 2022-05-10 18:46:00 +01:00
Tamas Vajk
db5afe84b4 Code quality improvement (fix warning) 2022-05-10 18:46:00 +01:00
Ian Lynagh
088e7adf8c Kotlin: Handle zero-width locations for generated elements 2022-05-10 18:46:00 +01:00
Tamas Vajk
76fd386055 Extract content of <obinit> methods 2022-05-10 18:46:00 +01:00
Tamas Vajk
b87c8e2529 Extract generated <obinit> method, and calls to it 2022-05-10 18:46:00 +01:00
Tamas Vajk
e31c573fb5 Remove redundant cast 2022-05-10 18:46:00 +01:00
Tamas Vajk
f18ab2e913 Reduce parameter passing, and compute label for enclosing callable on the fly 2022-05-10 18:46:00 +01:00
Tamas Vajk
13048392af Add constructor tests 2022-05-10 18:46:00 +01:00
Tamas Vajk
84e9fd8dbd Extract external types with members, so that tests don't produce DB constraint violations
The constructor of `Any` was missing. Also, previously members of external types were not extracted to not end up with DB constraint violations, but these I can't reproduce currently in tests.
2022-05-10 18:46:00 +01:00
Tamas Vajk
481c53a44d Fix merge conflict 2022-05-10 18:45:59 +01:00
Tamas Vajk
a46a9b579e Extract 'IsEnumType' 2022-05-10 18:45:59 +01:00
Tamas Vajk
5c72b52b97 Extract IrEnumConstructorCall 2022-05-10 18:45:59 +01:00
Tamas Vajk
9587e91f71 WIP: IrAnonymousInitializer/IrInstanceInitializerCall 2022-05-10 18:45:59 +01:00
Tamas Vajk
91eafafcc3 Extract delegating constructor calls 2022-05-10 18:45:59 +01:00
Tamas Vajk
661958488c Extract constructor calls 2022-05-10 18:45:59 +01:00
Ian Lynagh
2c5a2910d2 Kotlin: Add explorer 2022-05-10 18:45:59 +01:00
Tamas Vajk
5749dbf7d9 Fix package of Location 2022-05-10 18:45:59 +01:00
Tamas Vajk
ab77ed085f Add QL classes and tests for comments 2022-05-10 18:45:59 +01:00
Ian Lynagh
7d479943db Kotlin: Remove a redundant warning suppression 2022-05-10 18:45:59 +01:00
Ian Lynagh
93f6b23a91 Kotlin: Revert some now-unnecessary changes to dbscheme 2022-05-10 18:45:59 +01:00
Ian Lynagh
7eebf81ffc Kotlin: Remove some now-unnecessary casts 2022-05-10 18:45:59 +01:00
Ian Lynagh
bcbcd612a3 Kotlin: Improve the dbscheme generator
We now work out the supertype relationships based on the sets of leaf
types that are included, rather than simply following the hierarchy of
declarations. This means that we know about more supertype relationships
that exist, so there is less need to cast types.
2022-05-10 18:45:59 +01:00
Tamas Vajk
5aac46f20f Fix DB relation names to use plurals 2022-05-10 18:45:58 +01:00
Tamas Vajk
bf4fb13326 Revert extracting this and this@TYPE parameters 2022-05-10 18:45:58 +01:00
Tamas Vajk
d6ec230e2f Recognize qualified this access of outer class instance 2022-05-10 18:45:58 +01:00
Tamas Vajk
3bfc93daab Add ExtensionMethod class 2022-05-10 18:45:58 +01:00
Tamas Vajk
7d8b6bac06 Fix this and qualified this parameter extraction 2022-05-10 18:45:58 +01:00
Tamas Vajk
575e5134bb Extract 'this'-like value parameters 2022-05-10 18:45:58 +01:00
Tamas Vajk
ebee830a01 Handle type parameters which are nullable without question mark 2022-05-10 18:45:58 +01:00
Tamas Vajk
32a61c16cb Add break/continue QL and tests 2022-05-10 18:45:58 +01:00
Tamas Vajk
aa190f9d65 Store break/continue targets 2022-05-10 18:45:58 +01:00
Tamas Vajk
ae7aa30bda Extract break/continue/throw 2022-05-10 18:45:58 +01:00
Tamas Vajk
63c22ca5df Fix failing tests after changing external type declaration extraction 2022-05-10 18:45:58 +01:00
Tamas Vajk
9889f49560 Add QL for ::class expression, and add test 2022-05-10 18:45:58 +01:00
Tamas Vajk
e8a079b56a Extract all external class declarations (without members) 2022-05-10 18:45:58 +01:00
Tamas Vajk
1cc1daa88b Extract externally declared classes 2022-05-10 18:45:57 +01:00
Tamas Vajk
3e60841774 Extract ::class expressions 2022-05-10 18:45:57 +01:00
Tamas Vajk
f04eb6b1fa Add Nothing type test 2022-05-10 18:45:57 +01:00
Tamas Vajk
28afa19bf5 Change tests to select QL class name too 2022-05-10 18:45:57 +01:00
Tamas Vajk
9d76acad5c Add null extraction test 2022-05-10 18:45:57 +01:00
Tamas Vajk
f97c6af117 Extract nullable types as non-nullable 2022-05-10 18:45:57 +01:00
Tamas Vajk
fb44f1326f Extract Nothing as null 2022-05-10 18:45:57 +01:00
Tamas Vajk
f222fc6d42 Extract null literal 2022-05-10 18:45:57 +01:00
Ian Lynagh
bb3ebd7325 Kotlin: Fix warnElement counting
We were counting calls of warnElement, whereas we want to count its
callers.
2022-05-10 18:45:57 +01:00
Tamas Vajk
c64c950d9a Remove leftover comment class 2022-05-10 18:45:57 +01:00
Tamas Vajk
7ecb3650cb Cleanup getLabel 2022-05-10 18:45:57 +01:00
Tamas Vajk
48d019ebbe Fix review findings, add DB scheme for comments 2022-05-10 18:45:57 +01:00
Tamas Vajk
c23472d736 Rework and simplify comment extraction 2022-05-10 18:45:57 +01:00
Tamas Vajk
1c8be155c9 Extract comments (based on C# comments extraction with element stack) 2022-05-10 18:45:56 +01:00
Ian Lynagh
fd8dd21f75 Kotlin: Follow change in files(...) table 2022-05-10 18:45:56 +01:00
Ian Lynagh
598a2f8cb0 Kotlin: Record compilation and extraction times 2022-05-10 18:45:56 +01:00
Ian Lynagh
396b5882ef Kotlin: Add a compilations consistency query 2022-05-10 18:45:56 +01:00
Ian Lynagh
79e3cb38a8 Kotlin: Pull TrapWriter out into its own file 2022-05-10 18:45:56 +01:00
Ian Lynagh
2721f6aabf Kotlin: Pull Logger out into its own file 2022-05-10 18:45:56 +01:00
Ian Lynagh
e8d3125b40 Kotlin: Tweak a string 2022-05-10 18:45:56 +01:00
Chris Smowton
b5a8442e50 Extract type variable references
Also erase the types used to name methods; otherwise type-var labels and method labels are mutually recursive.
2022-05-10 18:45:56 +01:00
Ian Lynagh
87204f1634 Kotlin: Populate the compilation_compiling_files table 2022-05-10 18:45:56 +01:00
Ian Lynagh
dc3cc0e72e Kotlin: Refactoring: Give diagnostic messages locations and severities 2022-05-10 18:45:56 +01:00
Ian Lynagh
90eccc634b Kotlin: Refactor locations
Amongst other tidyups, we now generate correct "unknown location"s
2022-05-10 18:45:56 +01:00
Ian Lynagh
5c06ffae69 Kotlin: Use a TrapWriter for the invocation TRAP
We'll probably want to shuffle some more stuff from FileTrapWriter to
TrapWriter, but for now at least we are using the generated TRAP-writing
functions rather than writing raw TRAP.
2022-05-10 18:45:56 +01:00
Ian Lynagh
651847d202 Java/Kotlin: Enhance 'compilations' support 2022-05-10 18:45:56 +01:00
Tamas Vajk
9e4614e574 Add gitignore 2022-05-10 18:45:56 +01:00
Ian Lynagh
059d6798bb Kotlin: Tweak the definition of "eqwuivalent TRAP file"
TRAP files that only differ in their comments are equivalent
2022-05-10 18:45:55 +01:00
Ian Lynagh
c3dd35d98b Kotlin: Put temporary TRAP files in the correct directory 2022-05-10 18:45:55 +01:00
Ian Lynagh
774616450b Kotlin: Don't give stack traces for fake labels
There might be a significant performance hit for it.
2022-05-10 18:45:55 +01:00
Ian Lynagh
9bd0391c04 Kotlin: Don't fail if a file already exists in the source archive 2022-05-10 18:45:55 +01:00
Ian Lynagh
19ff50d0a6 Kotlin: Add a comment to each TRAP file linking to its invocation TRAP file 2022-05-10 18:45:55 +01:00
Ian Lynagh
4bc326ef82 Kotlin: Fix extraction when 2 invocations produce the same TRAP file
The second invocation was failing with a "file already exists" error.

I've also added a checkTrapIdentical flag, which is enabled for now.
This means that if 2 invocations write the same TRAP file, we will awrn
if they are not identical. It may be that this produces false positives,
but we can look at that if it happens.
2022-05-10 18:45:55 +01:00
Ian Lynagh
3e8f9f52a6 Kotlin: Start using invocation TRAP files 2022-05-10 18:45:55 +01:00
Ian Lynagh
71c3a64ff5 Kotlin: Simplify location extraction 2022-05-10 18:45:55 +01:00
Ian Lynagh
330727678a Kotlin: Add some location information to a warning 2022-05-10 18:45:55 +01:00
Ian Lynagh
486cff5df1 Kotlin: Add support for interfaces 2022-05-10 18:45:55 +01:00
Ian Lynagh
14e970044a Kotlin: Add some flushes
This will make it easier to see where we are if we get crashes in the
future.
2022-05-10 18:45:55 +01:00
Ian Lynagh
dbc3f29426 Kotlin: Put diagnostics in a TRAP file
Currently we just put everything in as severe with no location.
2022-05-10 18:45:55 +01:00
Ian Lynagh
a40ebd2520 Kotlin: Add support for supertypes 2022-05-10 18:45:55 +01:00
Ian Lynagh
d10024e7e9 Kotlin: Don't make a *Kt class unless we need one 2022-05-10 18:45:54 +01:00
Chris Smowton
c6deabd6a3 Update path to Java dbscheme
This changed when the Java tree was restructured for packaging
2022-05-10 18:45:54 +01:00
Ian Lynagh
f29a45ea98 Kotlin: Add getAPrimaryQlClass.ql consistenty check 2022-05-10 18:45:54 +01:00
Ian Lynagh
4837e4e46a Kotlin: More top-level stuff 2022-05-10 18:45:54 +01:00
Ian Lynagh
f0e2de1fa9 Kotlin: Add file classes
Kotlin invents a class for each file that has a top-level
functionp/property, so that Java can use them.
2022-05-10 18:45:54 +01:00
Ian Lynagh
ed2c6e68ea Kotlin: Function calls 2022-05-10 18:45:54 +01:00
Ian Lynagh
94eefbff17 Kotlin: Add IrContainerExpression 2022-05-10 18:45:54 +01:00
Ian Lynagh
e7cabfb965 Kotlin: Add assign exprs 2022-05-10 18:45:54 +01:00
Ian Lynagh
a64fedf764 Kotlin: When expressions 2022-05-10 18:45:54 +01:00
Ian Lynagh
bbb9d013e0 Kotlin: Escape TRAP strings 2022-05-10 18:45:54 +01:00
Ian Lynagh
f85cf27df8 Kotlin: Better logging infrastructure 2022-05-10 18:45:54 +01:00
Ian Lynagh
4ae7d19235 Kotlin: More expressions 2022-05-10 18:45:54 +01:00
Ian Lynagh
bb89b25e91 Kotlin: More expressions 2022-05-10 18:45:54 +01:00
Ian Lynagh
1de12e72d4 Kotlin: More expressions 2022-05-10 18:45:53 +01:00
Ian Lynagh
90161b9e9d Kotlin: Add more expressions 2022-05-10 18:45:53 +01:00
Ian Lynagh
492dc3dfb3 Kotlin: More tests (of unhandled expressions) 2022-05-10 18:45:53 +01:00
Ian Lynagh
b4bc40630f Kotlin: More expressions 2022-05-10 18:45:53 +01:00
Ian Lynagh
14a46b08b5 Kotlin: Variable accesses 2022-05-10 18:45:53 +01:00
Ian Lynagh
4c8ff16552 Kotlin: Fixes 2022-05-10 18:45:53 +01:00
Ian Lynagh
3daec4376f Kotlin: Variable initialisers 2022-05-10 18:45:53 +01:00
Ian Lynagh
f5e2826b9f Kotlin: Accept test changes 2022-05-10 18:45:53 +01:00
Ian Lynagh
4ba13d3663 Kotlin: Extract parameters 2022-05-10 18:45:53 +01:00
Ian Lynagh
799cf64fd2 Kotlin: Local variables 2022-05-10 18:45:53 +01:00
Ian Lynagh
46add88bb5 Kotlin: Add more types 2022-05-10 18:45:53 +01:00
Ian Lynagh
1c39f001e5 Kotlin: Add variables test 2022-05-10 18:45:53 +01:00
Ian Lynagh
b91660a0f0 Kotlin: Extract properties 2022-05-10 18:45:53 +01:00
Ian Lynagh
97722faee9 Kotlin: Add do/while loops 2022-05-10 18:45:52 +01:00
Ian Lynagh
0c429e4f80 Kotlin: Add blocks 2022-05-10 18:45:52 +01:00
Ian Lynagh
a8a6b4c09f Kotlin: Move some expressions to the right place 2022-05-10 18:45:52 +01:00
Ian Lynagh
b25ea03211 Kotlin: Add while statements 2022-05-10 18:45:52 +01:00
Ian Lynagh
00cff5593f Kotlin: Fix the tests
The handling of Unit is very kludgy at the moment. Will need rethinking.
2022-05-10 18:45:52 +01:00
Ian Lynagh
f0903726bf Kotlin: Add some if-stmt support 2022-05-10 18:45:52 +01:00
Ian Lynagh
d48739cc92 Kotlin: Check a call actually is an addition 2022-05-10 18:45:52 +01:00
Ian Lynagh
9a75ca7f62 Kotlin: Identify the int type better 2022-05-10 18:45:52 +01:00
Ian Lynagh
f608384085 Kotlin: Add a "bug" case 2022-05-10 18:45:52 +01:00
Ian Lynagh
b68178e8cc Kotlin: Handle enums better when generating dbscheme 2022-05-10 18:45:52 +01:00
Ian Lynagh
5f991653c1 Kotlin: Generate type aliases for dbscheme 2022-05-10 18:45:52 +01:00
Ian Lynagh
dbef421204 Kotlin: Generate dbscheme deterministically 2022-05-10 18:45:52 +01:00
Ian Lynagh
afea1871a7 Java: Add a variables consistency query 2022-05-10 18:45:52 +01:00
Ian Lynagh
15be80631f Java: Add a consistency test for expressions
They should have exactly 1 Type.
2022-05-10 18:45:52 +01:00
Ian Lynagh
bbbd5d78a7 Java: Add toString consistency query 2022-05-10 18:45:51 +01:00
Ian Lynagh
06d9d305c2 Java: More consistency queries 2022-05-10 18:45:51 +01:00
Ian Lynagh
b2acb7d7a1 Add a consistency query 2022-05-10 18:45:51 +01:00
Ian Lynagh
03d5646c19 Kotlin: Add stmt/expr support 2022-05-10 18:45:51 +01:00
Ian Lynagh
49a4e479da Kotlin: Extract methods 2022-05-10 18:45:51 +01:00
Ian Lynagh
6dd1027315 Kotlin: Refactoring 2022-05-10 18:45:51 +01:00
Ian Lynagh
fb26859425 Kotlin: Suppress an unchecked cast warning
I don't think we can easily do better here.
2022-05-10 18:45:51 +01:00
Ian Lynagh
4e27da33e4 Kotlin: Tweak generator 2022-05-10 18:45:51 +01:00
Ian Lynagh
d28059a1c0 Kotlin: Generate a module from the dbscheme 2022-05-10 18:45:51 +01:00
Ian Lynagh
4721ccd965 Kotlin: Add tests 2022-05-10 18:45:51 +01:00
Ian Lynagh
f15c6dede1 Kotlin: Get extractor working in a Java context 2022-05-10 18:45:51 +01:00
Ian Lynagh
e3ecf4c52d Kotlin: Add kotlin-extractor 2022-05-10 18:45:51 +01:00
Cornelius Riemenschneider
7c10f3e76b C#: Lua tracing config: Use API function. 2022-05-10 14:38:53 +00:00
Mathias Vorreiter Pedersen
1d10f14629 Merge pull request #9100 from redsun82/swift-tbd-rework
Swift: changes required for TBD node rework
2022-05-10 13:31:43 +01:00
Rasmus Wriedt Larsen
2b6e0cfb44 Merge pull request #8340 from yoff/python/simple-csrf
python: minimal CSRF implementation
2022-05-10 13:36:38 +02:00
Rasmus Wriedt Larsen
cb17e2a649 Merge pull request #8595 from porcupineyhairs/pypam
Python : Add query to detect PAM authorization bypass
2022-05-10 13:35:12 +02:00
Erik Krogh Kristensen
09360bce20 Merge pull request #9085 from erik-krogh/cash
JS: add model for the cash library
2022-05-10 13:20:57 +02:00
Paolo Tranquilli
bf71e4c500 Swift: getPrimaryQlClass -> getAPrimaryQlClass 2022-05-10 12:42:18 +02:00
Paolo Tranquilli
0b9dc9703f Swift: changes required for TBD node rework
These changes are required to allow a new type-safe approach to TBD
nodes, that will come in a separate commit.

This introduces:
* the possibility to add properties to the root `Element`
* a functor taking tags to the corresponding binding trap entry
* `hasProp()` methods for optional properties in QL
* `getPrimaryQlClass()` method
2022-05-10 11:59:25 +02:00
Rasmus Lerchedahl Petersen
aa3d7babf4 python: fix bad merge
caused by an optimistic attempt at solving a
merge conflict in the online GUI.
2022-05-10 11:37:41 +02:00
Rasmus Wriedt Larsen
2421076d2f Merge pull request #8696 from RasmusWL/new-nosql-examples
Python: Improve experimental modeling for `pymongo`
2022-05-10 11:03:05 +02:00
yoff
6c3e2db7fd Merge branch 'main' into python/simple-csrf 2022-05-10 10:55:28 +02:00
Cornelius Riemenschneider
7aa3d0fd26 Merge pull request #9091 from github/criemen/dotnet-lua-tracing-config
C#: Port the existing compiler-tracing.spec files to Lua.
2022-05-10 10:54:20 +02:00
Anders Schack-Mulligen
f85e06c2e4 Dataflow: Sync. 2022-05-10 10:12:39 +02:00
Cornelius Riemenschneider
40503aa368 Address review. 2022-05-10 08:06:25 +00:00
yoff
b6605bc330 Merge pull request #8634 from RasmusWL/promote-xxe
Python: Promote XXE and XML-bomb queries
2022-05-09 21:54:55 +02:00
Rasmus Lerchedahl Petersen
1c7e533144 python: format 2022-05-09 21:22:27 +02:00
Erik Krogh Kristensen
e80ee46fe4 add model for the cash library 2022-05-09 21:01:07 +02:00
Mathias Vorreiter Pedersen
66ca01a717 Merge pull request #9094 from redsun82/swift-codegen-predicate-properties
Swift codegen: add predicate properties
2022-05-09 17:17:10 +01:00
luchua-bc
75e7148912 Standardize the query and update qldoc 2022-05-09 16:10:11 +00:00
Paolo Tranquilli
c08e6fdc1e Swift codegen: add predicate properties
Properties marked with `predicate` in the schema are now accepted.

* in the dbscheme, they will translate to a table with a single `id`
  column (and the table name will not be pluralized)
* in C++ classes, they will translate to `bool` fields
* in QL classes, they will translate to predicates

Closes https://github.com/github/codeql-c-team/issues/1016
2022-05-09 17:50:49 +02:00
Paolo Tranquilli
effa9ee207 Merge pull request #9034 from redsun82/swift-cpp-gen
Swift: add structured C++ generated classes
2022-05-09 17:49:23 +02:00
Geoffrey White
265500faa8 Merge pull request #8800 from geoffw0/unsafeput
C++: Add a test for experimental query NoCheckBeforeUnsafePutUser.ql.
2022-05-09 16:20:19 +01:00
Rasmus Lerchedahl Petersen
2a5908ff49 python: require all settings be vulnerable
at least all thos not in tests
2022-05-09 17:08:49 +02:00
Cornelius Riemenschneider
bf0e32ae82 C#: Port the existing compiler-tracing.spec files to Lua. 2022-05-09 14:45:34 +00:00
Rasmus Wriedt Larsen
4a6789182d Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2022-05-09 16:37:12 +02:00
Anders Schack-Mulligen
135d7f6e32 Dataflow: Prune more cons-candidates. 2022-05-09 16:21:12 +02:00
Anders Schack-Mulligen
1b0e9d5cd7 Dataflow: Fix join order in nodeMayUseSummary. 2022-05-09 16:21:12 +02:00
Henry Mercer
3c4715928e Merge pull request #9083 from github/henrymercer/fetch-codeql-with-gh-cli
Actions: Fetch CodeQL CLI using `gh` rather than third-party Action
2022-05-09 14:40:29 +01:00
Anders Schack-Mulligen
f24364d951 Merge pull request #9045 from hvitved/dataflow/subpaths-perf-take2
Data flow: Speedup `subpaths` predicate (take 2)
2022-05-09 15:39:11 +02:00
Henry Mercer
71d1069a0a Fix typo 2022-05-09 14:31:05 +01:00
Henry Mercer
198c96982c Add a comment to explain the unusual Action path 2022-05-09 14:30:41 +01:00
CodeQL CI
e099b94cc4 Merge pull request #9081 from asgerf/js/global-step-refactor
Approved by erik-krogh
2022-05-09 06:30:37 -07:00
Rasmus Wriedt Larsen
c218162104 Merge branch 'main' into pypam 2022-05-09 14:20:05 +02:00
Rasmus Wriedt Larsen
ab1252d196 Python: Add @precision high for py/pam-auth-bypass 2022-05-09 14:19:40 +02:00
Geoffrey White
85cc9b8901 C++: Use getClassAndName. 2022-05-09 13:06:44 +01:00
Geoffrey White
28dca3fa9f Merge pull request #8245 from ihsinme/ihsinme-patch-67
CPP: Add query for CWE-476: NULL Pointer Dereference when using exception handling blocks
2022-05-09 12:26:20 +01:00
Geoffrey White
9709c2fa94 C++: Use compliant PascalCase / make the checks happy. 2022-05-09 11:58:57 +01:00
Henry Mercer
804ca3e1a7 Actions: Fetch CodeQL CLI using gh rather than third-party Action 2022-05-09 11:42:01 +01:00
Erik Krogh Kristensen
53b26eba17 Merge pull request #8724 from erik-krogh/postMessage
JS: promote the `js/missing-origin-verification` query
2022-05-09 12:28:58 +02:00
Erik Krogh Kristensen
fe1e47bc17 Merge pull request #8710 from bananabr/dragAndDrop
JS: drag and drop API Xss sources
2022-05-09 12:22:28 +02:00
Erik Krogh Kristensen
611a412f2a Merge pull request #8990 from bananabr/selection
JS: Selection API DOM text source
2022-05-09 12:22:18 +02:00
Paolo Tranquilli
93f8b6b29d Swift: add missing trap_affix 2022-05-09 12:20:22 +02:00
Paolo Tranquilli
20317a280b Swift: make width fields unsigned 2022-05-09 12:19:52 +02:00
Asger F
88b5bbe024 JS: Update test expectation 2022-05-09 11:55:07 +02:00
Rasmus Wriedt Larsen
de05b108fa Python: Fix singleton set 2022-05-09 11:01:13 +02:00
Rasmus Wriedt Larsen
36349222a9 Python: Fix casing of XMLDomParsing 2022-05-09 11:00:25 +02:00
Rasmus Wriedt Larsen
f22bd039f3 Python: Slight refactor of LxmlParsing 2022-05-09 10:56:39 +02:00
Rasmus Wriedt Larsen
f5854f33da Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2022-05-09 10:53:25 +02:00
Michael Nebel
9a45949e8c Merge pull request #9044 from michaelnebel/csharp/flowsummariestest
C#: Flow summaries test should print, whether a summary is generated or not.
2022-05-09 10:06:19 +02:00
Michael Nebel
1401e7ddb3 Merge pull request #8855 from michaelnebel/csharp/singlereadstore
C#: Only allow two read and two store steps in model capturing.
2022-05-09 10:05:53 +02:00
Paolo Tranquilli
9c5b2d7e9d Swift: tweaks for use in the PoC branch 2022-05-09 09:46:47 +02:00
Paolo Tranquilli
918ba1b1fc Swift: make generator.run accept options 2022-05-09 09:34:49 +02:00
AlexDenisov
c21849bb2e Merge pull request #9015 from redsun82/swift-enable-dynamic-library
Swift: enable dynamic mode
2022-05-09 09:15:37 +02:00
AlexDenisov
fe72dfe7d4 Merge pull request #9028 from redsun82/swift-trapgen
Swift: add `trapgen` unit tests
2022-05-09 09:15:22 +02:00
Paolo Tranquilli
6cbfb5a10c Swift cppgen: emit final trap before bases 2022-05-09 09:02:20 +02:00
Michael Nebel
83aa65ff53 C#/Java: Remove redudandant QL comment in CaptureModel. 2022-05-09 07:36:41 +02:00
Michael Nebel
76fd424795 C#: Turn isAutogenerated predicate into a predicate without result. 2022-05-09 07:30:06 +02:00
Michael Nebel
9b855c30cc Merge pull request #9043 from michaelnebel/csharp/xml-injection-path
C#: Convert xml injection query to a path problem.
2022-05-09 07:18:01 +02:00
Marcono1234
c760d39d59 Merge remote-tracking branch 'remotes/origin/main' into marcono1234/statement-expression 2022-05-09 00:28:19 +02:00
Marcono1234
36f56b5a18 Java: Rename StmtExpr to ValueDiscardingExpr
As mentioned by aschackmull during review, StatementExpression as defined
by the JLS only lists possible types of expressions, it does _not_ specify
that their value is discarded. Therefore, for example any method call could
be considered a StatementExpression.

The name ValueDiscardingExpr was chosen as replacement because the JLS uses
the phrase "if the expression has a value, the value is discarded" multiple
times.
2022-05-09 00:27:15 +02:00
Mathias Vorreiter Pedersen
176e40f139 Merge pull request #9052 from github/post-release-prep/codeql-cli-2.9.1
Post-release preparation for codeql-cli-2.9.1
2022-05-06 13:15:17 +01:00
github-actions[bot]
1a25457178 Post-release preparation for codeql-cli-2.9.1 2022-05-05 19:05:50 +00:00
ihsinme
b98ddc72f5 Update DangerousUseOfExceptionBlocks.ql 2022-05-05 21:05:22 +03:00
Paolo Tranquilli
a7129c1f4c Swift: add --ql-format/--no-ql-format to codegen 2022-05-05 18:33:05 +02:00
ihsinme
6dec1182bf Update DangerousUseOfExceptionBlocks.expected 2022-05-05 19:17:31 +03:00
ihsinme
185a60f034 Update test.cpp 2022-05-05 19:16:54 +03:00
Geoffrey White
453dadea1a C++: Fix QLDoc. 2022-05-05 16:43:31 +01:00
ihsinme
2d4d7aa094 Update DangerousUseOfExceptionBlocks.ql 2022-05-05 18:40:29 +03:00
Geoffrey White
6b5a1921dd C++: Support the SAX2XMLReader interface. 2022-05-05 16:35:21 +01:00
Paolo Tranquilli
b2b5fd281f Swift: add more parametrization
This enables codegen to run on the swift PoC branch.
2022-05-05 17:34:00 +02:00
Geoffrey White
c4bc7050a9 C++: Additional test cases. 2022-05-05 16:26:09 +01:00
Tony Torralba
ca2959cf37 Merge pull request #8537 from atorralba/atorralba/unsafe_android_access_improvs
Java: Improvements to UnsafeAndroidAccess
2022-05-05 16:46:54 +02:00
Paolo Tranquilli
ac3cceab19 Swift: turn some generated paths to relative 2022-05-05 16:15:16 +02:00
Paolo Tranquilli
7bcc5db4a6 Swift: parametrize namespace and other things in codegen
This is so that we can use this in the PoC branch.
2022-05-05 16:01:54 +02:00
Tom Hvitved
04cc73823d Java: Introduce 'with/without content' summary components 2022-05-05 14:25:48 +02:00
Tom Hvitved
2972af2602 C#: Introduce 'with/without content' summary components 2022-05-05 14:25:48 +02:00
Tom Hvitved
2e780154e2 Ruby: Introduce 'with/without content' summary components 2022-05-05 14:25:48 +02:00
yoff
6169ac6122 Merge pull request #7776 from RasmusWL/django-filefield-uploadto
Python: Support Django FileField.upload_to
2022-05-05 14:25:08 +02:00
Erik Krogh Kristensen
58db9226dc add missing word in qhelp 2022-05-05 14:24:45 +02:00
Tom Hvitved
d9d5372f28 Data flow: Sync files 2022-05-05 13:36:26 +02:00
Tom Hvitved
de6e2c95e7 Data flow: Speedup subpaths predicate (take 2) 2022-05-05 13:36:08 +02:00
Michael Nebel
3c347cab98 C#: Update test output to reflect that the query is now a path-problem query. 2022-05-05 13:13:25 +02:00
Michael Nebel
2dc35c123a Java/Ruby: Sync files. 2022-05-05 13:08:55 +02:00
Michael Nebel
a8556f4d50 C#: Make sure that test output prints whether the summary is generated or not. 2022-05-05 13:07:22 +02:00
Erik Krogh Kristensen
2d7c7ff372 apply suggestions from doc review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2022-05-05 13:03:35 +02:00
Asger F
c4d597d60f JS: Enumerate type-tracking steps through global access paths 2022-05-05 12:59:10 +02:00
ihsinme
75244effc5 Update DangerousUseOfExceptionBlocks.ql 2022-05-05 13:27:17 +03:00
Paolo Tranquilli
c87fb4df53 Swift: remove now unused ql.Property.params 2022-05-05 12:01:13 +02:00
Mathias Vorreiter Pedersen
6f9752ead1 Merge pull request #9019 from geoffw0/xxe4
C++: More XXE Tests
2022-05-05 10:59:40 +01:00
Michael Nebel
e416a0629a C#: Add isAutoGenerated predicate to SummarizedCallable. 2022-05-05 11:54:04 +02:00
Paolo Tranquilli
9798d8ba26 Swift: add ?* modifier to schema specification
This indicates a list of optional entries. This is different than
simply repeatind entries because of the indexing.
2022-05-05 11:50:12 +02:00
yoff
0c7184952b Merge pull request #9023 from RasmusWL/positional-docs
Python: Clarify `getArg` is about positional arguments
2022-05-05 11:28:17 +02:00
Arthur Baars
25d9ffd18c Merge pull request #9033 from github/aibaars/atm-label
JS: exclude ATM folder from labeler
2022-05-05 10:53:39 +02:00
Michael Nebel
13f142f143 C#: Convert xml injection query to a path problem. 2022-05-05 10:43:23 +02:00
Jonas Jensen
d747c6eaa9 Merge pull request #8930 from jbj/lower-case-variables-spec
QL language reference: variables must be lowerId
2022-05-05 10:02:16 +02:00
Paolo Tranquilli
c2d3aac349 Swift: fix no functools.cache in python 3.8 2022-05-05 09:48:07 +02:00
Michael Nebel
21eb5a1db5 Merge pull request #8894 from michaelnebel/csharp/upgrade-dotnet
C#: Upgrade dotnet to 6.0.202.
2022-05-05 09:42:23 +02:00
Erik Krogh Kristensen
bf6663ab12 run the autoformatter 2022-05-05 09:16:27 +02:00
Tom Hvitved
66a9759329 Merge pull request #8870 from hvitved/dataflow/expect-content
Data flow: Introduce `expectsContent`
2022-05-05 09:01:40 +02:00
luchua-bc
937ab417b1 Query to detect hardcoded JWT secret keys 2022-05-04 23:09:48 +00:00
Daniel Santos
33e85f8db8 Update javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2022-05-04 11:43:56 -05:00
Paolo Tranquilli
d5d1eb717d Swift: add structured C++ generated classes
This adds `cppgen`, creating structured C++ classes mirroring QL classes
out of `schema.yml`.

An example of generated code at the time of this commit can be found
[in this gist][1].

[1]: https://gist.github.com/redsun82/57304ddb487a8aa40eaa0caa695048fa

Closes https://github.com/github/codeql-c-team/issues/863
2022-05-04 18:20:25 +02:00
Paolo Tranquilli
10c5c8e71f Swift: add trapgen unit tests
Closes: https://github.com/github/codeql-c-team/issues/981
2022-05-04 18:20:06 +02:00
Tom Hvitved
8e33653d25 Merge pull request #9017 from hvitved/dataflow/subpaths-perf
Data flow: Speedup `subpaths` predicate
2022-05-04 16:37:52 +02:00
Erik Krogh Kristensen
0d8bef7e92 Merge pull request #6736 from erik-krogh/polyReplace
JS: track flow through string replace calls that just replace single chars for js/polynomial-redos
2022-05-04 16:30:20 +02:00
Erik Krogh Kristensen
8425eaf919 Merge pull request #8549 from erik-krogh/unreachableJoin
JS: fix bad join in js/unreachable-method-overloads
2022-05-04 16:28:06 +02:00
Erik Krogh Kristensen
b4d4b51bc7 Merge pull request #8147 from erik-krogh/cacheReg
JS: cache RegExpCreationNode::getAReference
2022-05-04 16:25:25 +02:00
Arthur Baars
c7b2da5e39 JS: exclude ATM folder from labeler 2022-05-04 16:16:19 +02:00
Rasmus Wriedt Larsen
7bd7bedb1b Ruby: Simplify isLocalSourceNode implementation
The need for `SynthReturnNode` goes away if we don't restrict the nodes
that can't be reached from another entry definition or expression to be
`ExprNode`s
2022-05-04 16:12:20 +02:00
Nick Rolfe
5f59e96fa9 Merge pull request #8975 from github/nickrolfe/flow_summary_joins 2022-05-04 14:24:45 +01:00
Tom Hvitved
9cb63c0a5e Data flow: Sync files 2022-05-04 14:49:26 +02:00
Tom Hvitved
7f7742216c Address review comment
This reverts commit 2b4fde74bb.
2022-05-04 14:49:03 +02:00
Nick Rolfe
276f8d40f9 Ruby: add comments to address review feedback 2022-05-04 12:07:46 +01:00
Mathias Vorreiter Pedersen
f499f8e946 Merge pull request #9029 from redsun82/swift-codeowners
Swift: set @github/codeql-c as owner
2022-05-04 11:34:51 +01:00
Tony Torralba
2d3b15f936 Add more taint models 2022-05-04 12:32:59 +02:00
Michael Nebel
5f1a176a02 Java: Sync CaptureModels implementation to only allow at most two reads and two stores. 2022-05-04 12:29:57 +02:00
Michael Nebel
a488d6b80c C#: Add an initial flow state to the model generator. 2022-05-04 12:27:34 +02:00
Tony Torralba
8601137602 Fix bad join order by moving WebViewRef::getAnAccess from callsites into predicates 2022-05-04 11:58:47 +02:00
Tony Torralba
3b1210eacb Update java/ql/lib/semmle/code/java/security/UnsafeAndroidAccess.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2022-05-04 10:53:31 +02:00
Tony Torralba
192017635a Update java/ql/src/change-notes/2022-03-24-unsafe-android-access-improvements.md
Co-authored-by: Chris Smowton <smowton@github.com>
2022-05-04 10:53:31 +02:00
Tony Torralba
49259a6575 Remove everything related to WebView CSV models
This reverts commit c6c72eb.
2022-05-04 10:53:31 +02:00
Tony Torralba
dce11f3984 Removed unnecessary imports 2022-05-04 10:53:30 +02:00
Tony Torralba
f5e72e6e33 Remove getUnderlyingExpr 2022-05-04 10:53:30 +02:00
Tony Torralba
7ba5a032ce Add tests and stubs for the new sources and flow steps 2022-05-04 10:53:30 +02:00
Tony Torralba
b678467e9d Move things around 2022-05-04 10:53:30 +02:00
Tony Torralba
d68311e26d Consider implicit this accesses in WebViewRef 2022-05-04 10:53:30 +02:00
Tony Torralba
51dfebf4c9 Apply suggestions from code review
Co-authored-by: Chris Smowton <smowton@github.com>
2022-05-04 10:53:29 +02:00
Tony Torralba
b9859fe165 Add change note 2022-05-04 10:53:29 +02:00
Tony Torralba
91bdb4299f Improvements to UnsafeAndroidAccess 2022-05-04 10:53:29 +02:00
Tony Torralba
b876431950 Merge pull request #8706 from luchua-bc/java/unsafe-get-resource
Java: CWE-552 Add sources and sinks to to detect unsafe getResource calls in Java EE applications
2022-05-04 10:12:28 +02:00
Tom Hvitved
74e99302d6 Address review comments 2022-05-04 09:57:59 +02:00
Tom Hvitved
ac3bfa1788 Data flow: Mention expectsContent in dataflow.md 2022-05-04 09:57:59 +02:00
Tom Hvitved
da72ba46d4 Data flow: Add stub expectsContent for all languages 2022-05-04 09:57:59 +02:00
Tom Hvitved
6e2e8440eb Data flow: Sync files 2022-05-04 09:57:59 +02:00
Tom Hvitved
a50f18ab50 Data flow: Introduce expectsContent 2022-05-04 09:57:58 +02:00
bananabr
2e2d4c6e1f updated tests to consider document.getSelection() 2022-05-03 21:03:35 -05:00
Daniel Santos
880e3e1885 Update javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2022-05-03 11:38:32 -05:00
Daniel Santos
4cd6dcc4d0 Update javascript/ql/lib/change-notes/2022-04-30-xss-selection-source.md
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2022-05-03 11:37:45 -05:00
Daniel Santos
d52980573a Update javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2022-05-03 11:37:26 -05:00
Paolo Tranquilli
b7cdc4ae1f Swift: set @github/codeql-c as owner 2022-05-03 17:41:23 +02:00
Geoffrey White
5aa862acfd C++: Fixup after merge. 2022-05-03 16:12:42 +01:00
Geoffrey White
fd5b4dfff2 Merge branch 'main' into xxe4 2022-05-03 16:08:54 +01:00
Mathias Vorreiter Pedersen
b8fd07c0ac Merge pull request #9018 from geoffw0/xxe5
C++: Support libxml2 in the XXE query
2022-05-03 16:00:52 +01:00
Michael Nebel
b8ec2254e8 C#: Update unit tests (looks like new NFloat operator has been introduced). 2022-05-03 16:36:32 +02:00
Michael Nebel
94b046c554 C#: Upgrade dotnet to 6.0.202. 2022-05-03 16:36:32 +02:00
Joe Farebrother
f65f833b11 Merge pull request #9020 from joefarebrother/predictable-seed
Java: Add CWE-377 tag to java/predictable-seed
2022-05-03 15:13:58 +01:00
Tony Torralba
02822c6284 Merge pull request #9013 from atorralba/atorralba/private-externalflow-imports
Java: Make more ExternalFlow imports private
2022-05-03 16:02:09 +02:00
Tony Torralba
cf55f180c4 Add change note 2022-05-03 15:46:17 +02:00
Tony Torralba
7b3a803d19 Add flow step from startActivity to getIntent 2022-05-03 15:46:17 +02:00
Tony Torralba
9c92454fa7 Merge pull request #8872 from atorralba/atorralba/android-widget-flowstep
Java: Add Editable.toString flow step
2022-05-03 15:27:52 +02:00
Joe Farebrother
61f13817cf Add change note 2022-05-03 14:27:47 +01:00
Geoffrey White
d5be11bf14 C++: Address review comments. 2022-05-03 14:08:19 +01:00
Rasmus Wriedt Larsen
a7b43f7356 Ruby: Accept changes to TypeTracker tests
Since this is not using inline-expectation-tests, I'm not entirely sure
whether these changes are OK or not, so hope to get someone else to
signoff on that.
2022-05-03 14:59:06 +02:00
Rasmus Wriedt Larsen
6cacf7b9a6 Ruby: isLocalSourceNode needs SynthReturnNode 2022-05-03 14:43:57 +02:00
Tony Torralba
fbceb8de57 Update java/ql/lib/semmle/code/java/frameworks/OkHttp.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2022-05-03 14:40:40 +02:00
Rasmus Wriedt Larsen
d012eaa892 Python: Clarify getArg is about positional arguments 2022-05-03 14:26:23 +02:00
Rasmus Wriedt Larsen
89c4b6c235 Ruby: Fix isLocalSourceNode implementation
The old code was equivalent with the code below, which seems wrong

```
not n instanceof ExprNode
or
n instanceof ExprNode and
localFlowStepTypeTracker+(..., n)
```

From running on real DB I found that this meant that the following node
types were also included as local source nodes:

- `TReturningNode`
- `TSynthReturnNode`
- `TSummaryNode`
- `TSsaDefinitionNode`

My understanding is that the first 3 should not be included.

I would guess that SsaDefinitionNode should indeed be included as a
LocalSourceNode, but I'm not 100% sure, so I'll see what the test
results say before making further changes.
2022-05-03 14:16:19 +02:00
Joe Farebrother
f7d0884db1 Java: Add cwe-377 tag to predictable-seed 2022-05-03 12:28:14 +01:00
Geoffrey White
42a78a27e0 C++: Fixup spacing in tests. 2022-05-03 11:48:03 +01:00
Paolo Tranquilli
c2be267feb Swift: enable dynamic mode
Providing `--dynamic_mode=fully` (for example setting it in
`local.bazelrc`) will now work.

All runfiles are now copied in the extractor pack: in dynamic mode,
those will be the executable and the dynamic libraries, while in static
mode only the executable will be part of the runfiles.

Setting the correct `LD_LIBRARY_PATH` in `qltest.sh` then allows to
run tests with this pakcage. If we need something more, we can switch to
a wrapper script in place of `extractor` in the future.

Notice that `LD_LIBRARY_PATH` is also set in static mode, but that has
no consequence.
2022-05-03 12:33:24 +02:00
yoff
56ed68b3eb Merge pull request #9001 from RasmusWL/files-refactoring
Python: Flask: Improve `request.files` modeing
2022-05-03 12:19:55 +02:00
Geoffrey White
9faa825304 C++: Add support for libxml2 in the query. 2022-05-03 11:19:13 +01:00
Tom Hvitved
e9c8f979f9 Data flow: Sync files 2022-05-03 11:46:51 +02:00
Tom Hvitved
2b4fde74bb Data flow: Speedup subpaths predicate
Before
```
[2022-05-02 15:47:16] (1280s) Tuple counts for DataFlowImpl::Subpaths::subpaths#656de156#ffff/4@c5f3dclb after 3m22s:
                      8389013    ~4%     {5} r1 = JOIN DataFlowImpl::Subpaths::subpaths#656de156#ffff#shared WITH DataFlowImpl::PathNode::getASuccessor#dispred#f0820431#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'arg', Lhs.1, Lhs.2, Lhs.3, Lhs.4 'out'
                      6689751    ~0%     {4} r2 = JOIN r1 WITH DataFlowImpl::Subpaths::subpaths03#656de156#ffffff_034512#join_rhs ON FIRST 4 OUTPUT Rhs.4, Lhs.4 'out', Lhs.0 'arg', Rhs.5 'ret'

                      1513839768 ~1%     {5} r3 = JOIN r2 WITH DataFlowImpl::PathNodeImpl::getNodeEx#dispred#f0820431#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'out', Lhs.2 'arg', Lhs.3 'ret', Rhs.1 'par', Lhs.3 'ret'
                      1513839768 ~1%     {5} r4 = r3 AND NOT DataFlowImpl::PathNodeImpl::isHidden#dispred#f0820431#f(Lhs.4 'ret')
                      1513839768 ~5%     {4} r5 = SCAN r4 OUTPUT In.1 'arg', In.3 'par', In.0 'out', In.4 'ret'

                      1513839768 ~2%     {4} r6 = JOIN r2 WITH DataFlowImpl::PathNodeImpl::getNodeEx#dispred#f0820431#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.3 'ret', Lhs.1 'out', Lhs.2 'arg', Rhs.1 'par'
                      0          ~0%     {5} r7 = JOIN r6 WITH boundedFastTC(DataFlowImpl::Subpaths::localStepToHidden#656de156#ff_10#higher_order_body,DataFlowImpl::Subpaths::subpaths#656de156#ffff#higher_order_body) ON FIRST 1 OUTPUT Lhs.1 'out', Lhs.2 'arg', Lhs.0, Lhs.3 'par', Rhs.1 'ret'
                      0          ~0%     {5} r8 = r7 AND NOT DataFlowImpl::PathNodeImpl::isHidden#dispred#f0820431#f(Lhs.4 'ret')
                      0          ~0%     {4} r9 = SCAN r8 OUTPUT In.1 'arg', In.3 'par', In.0 'out', In.4 'ret'

                      1513839768 ~5%     {4} r10 = r5 UNION r9
                      6689751    ~0%     {4} r11 = JOIN r10 WITH DataFlowImpl::PathNode::getASuccessor#dispred#f0820431#ff ON FIRST 2 OUTPUT Lhs.0 'arg', Lhs.1 'par', Lhs.3 'ret', Lhs.2 'out'
                                         return r11
```

After
```
[2022-05-03 11:44:10] (969s) Tuple counts for DataFlowImpl::Subpaths::subpaths#656de156#ffff/4@b26b969r after 11.8s:
                      8372525 ~0%     {3} r1 = JOIN DataFlowImpl::PathNode::getASuccessor#dispred#f0820431#ff_10#join_rhs WITH DataFlowImpl::PathNodeImpl::getNodeEx#dispred#f0820431#ff ON FIRST 1 OUTPUT Lhs.1 'arg', Rhs.1, Rhs.0
                      6673799 ~6%     {9} r2 = JOIN r1 WITH DataFlowImpl::Subpaths::subpaths03#656de156#fffffffff ON FIRST 2 OUTPUT Rhs.3, Rhs.4, Rhs.5, Rhs.7, Rhs.6, Rhs.8, Lhs.2 'par', Lhs.0 'arg', Rhs.2 'ret'

                      6637884 ~0%     {5} r3 = JOIN r2 WITH project#DataFlowImpl::pathNode#656de156#ffffffff_1234560#join_rhs ON FIRST 6 OUTPUT Lhs.6 'par', Lhs.7 'arg', Lhs.8 'ret', Rhs.6 'out', Lhs.8 'ret'

                      6637884 ~0%     {4} r4 = JOIN r2 WITH project#DataFlowImpl::pathNode#656de156#ffffffff_1234560#join_rhs ON FIRST 6 OUTPUT Rhs.6 'out', Lhs.6 'par', Lhs.7 'arg', Lhs.8 'ret'

                      51867   ~0%     {5} r5 = JOIN r4 WITH DataFlowImpl::PathNodeMid::projectToSink#dispred#f0820431#ff ON FIRST 1 OUTPUT Lhs.1 'par', Lhs.2 'arg', Lhs.3 'ret', Rhs.1 'out', Lhs.3 'ret'

                      6689751 ~0%     {5} r6 = r3 UNION r5
                      6689751 ~0%     {5} r7 = r6 AND NOT DataFlowImpl::PathNodeImpl::isHidden#dispred#f0820431#f(Lhs.4 'ret')
                      6689751 ~0%     {4} r8 = SCAN r7 OUTPUT In.1 'arg', In.0 'par', In.4 'ret', In.3 'out'

                      6637884 ~0%     {4} r9 = JOIN r2 WITH project#DataFlowImpl::pathNode#656de156#ffffffff_1234560#join_rhs ON FIRST 6 OUTPUT Lhs.8 'ret', Lhs.6 'par', Lhs.7 'arg', Rhs.6 'out'

                      51867   ~0%     {4} r10 = JOIN r4 WITH DataFlowImpl::PathNodeMid::projectToSink#dispred#f0820431#ff ON FIRST 1 OUTPUT Lhs.3 'ret', Lhs.1 'par', Lhs.2 'arg', Rhs.1 'out'

                      6689751 ~0%     {4} r11 = r9 UNION r10
                      0       ~0%     {5} r12 = JOIN r11 WITH boundedFastTC(DataFlowImpl::Subpaths::localStepToHidden#656de156#ff_10#higher_order_body,DataFlowImpl::Subpaths::subpaths#656de156#ffff#higher_order_body) ON FIRST 1 OUTPUT Lhs.1 'par', Lhs.2 'arg', Lhs.0, Lhs.3 'out', Rhs.1 'ret'
                      0       ~0%     {5} r13 = r12 AND NOT DataFlowImpl::PathNodeImpl::isHidden#dispred#f0820431#f(Lhs.4 'ret')
                      0       ~0%     {4} r14 = SCAN r13 OUTPUT In.1 'arg', In.0 'par', In.4 'ret', In.3 'out'

                      6689751 ~0%     {4} r15 = r8 UNION r14
                                      return r15
```
2022-05-03 11:45:28 +02:00
Anders Schack-Mulligen
249f771fad Merge pull request #8952 from cklin/fix-ql-comments-syntax
Fix syntax errors in QL comments
2022-05-03 11:15:56 +02:00
Jeroen Ketema
904ff1a569 Merge pull request #8943 from jbj/remove-gvn-imports
C++: Remove import order workarounds
2022-05-03 11:01:02 +02:00
Nick Rolfe
00bf352b50 Ruby: fix some flow summary join orders
The flow summaries that are implemented with an abstract base class
restricting the method name, and child classes using that method name,
had unfortunate join orders:

r1 = JOIN Call::MethodCall::getMethodName#dispred#f0820431#ff WITH Call::MethodCall::getMethodName#dispred#f0820431#ff ON FIRST 1 OUTPUT Lhs.0, (Lhs.1 ++ "_arg"), Rhs.1
2022-05-03 09:58:40 +01:00
mc
58a2677cf7 Merge pull request #8860 from github/jf205-patch-1
Fix broken link in analyzing-databases-with-the-codeql-cli.rst
2022-05-03 09:56:49 +01:00
Mathias Vorreiter Pedersen
73886b1040 Merge pull request #8948 from geoffw0/xxe3
C++: Add support for SAXParser to the CWE-611 XXE query.
2022-05-03 09:42:10 +01:00
Tony Torralba
c66e583aea Make more ExternalFlow imports private 2022-05-03 10:31:29 +02:00
Arthur Baars
19e4d34581 Update ruby/ql/lib/change-notes/2022-04-30-update-grammar.md
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
2022-05-03 10:08:29 +02:00
Erik Krogh Kristensen
806dacb0e3 Merge pull request #8989 from erik-krogh/mentionAll
JS/RB: have `ApiGraphModelsSpecific.qll` mention all the required predicates
2022-05-03 09:42:41 +02:00
Tony Torralba
5c574906fe Merge pull request #9010 from github/workflow/coverage/update
Update CSV framework coverage reports
2022-05-03 09:23:53 +02:00
github-actions[bot]
433beaf637 Add changed framework coverage reports 2022-05-03 00:15:34 +00:00
Daniel Santos
fddb465260 Update javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2022-05-02 14:00:45 -05:00
Tony Torralba
de8b5f927b Adjust test expectations 2022-05-02 16:55:11 +02:00
Tony Torralba
29b430e49b Make commits private 2022-05-02 16:55:01 +02:00
Anders Schack-Mulligen
86516b157b Merge pull request #8884 from JLLeitschuh/feat/JLL/additional-file-taint-flow
Java: Add additional `File` taint value flow models
2022-05-02 16:30:45 +02:00
Tony Torralba
9a35aba465 Add change notes 2022-05-02 15:45:44 +02:00
Tony Torralba
1cf4b60769 Simplify non-https-url query 2022-05-02 15:43:07 +02:00
Tony Torralba
8602a6f6c9 Add models for OkHttp and Retrofit 2022-05-02 15:42:15 +02:00
Rasmus Wriedt Larsen
7e1be3172e Python: Add change-note 2022-05-02 14:24:13 +02:00
Rasmus Wriedt Larsen
de4390cdf6 Python: Improve Flask request.files handling even more 2022-05-02 14:19:45 +02:00
Rasmus Wriedt Larsen
fb0133d276 Python: Fix Flask request.files modeling 2022-05-02 14:14:58 +02:00
Rasmus Wriedt Larsen
0c62916af5 Python: Highlight problem with Flask request.files modeling 2022-05-02 14:14:53 +02:00
yoff
1d44694280 Merge pull request #8732 from RasmusWL/dataflow-imports
Python: Don't re-export `python` under `DataFlow::`
2022-05-02 12:08:28 +02:00
Taus
231def026f Merge pull request #8890 from tausbn/python-add-global-attribute-writes
Python: Add support for global attribute writes
2022-05-02 12:03:41 +02:00
yoff
c67b06b1fd Update python/ql/test/experimental/dataflow/typetracking/attribute_tests.py
Co-authored-by: Taus <tausbn@github.com>
2022-05-02 11:36:58 +02:00
Rasmus Wriedt Larsen
714465bf39 Python: Refactor SaxParserSetFeatureCall
Originally made by @erik-krogh in
https://github.com/github/codeql/pull/8693/files#diff-9627c1fb9a1cc77fb93e6b7e31af1a4fa908f2a60362cfb34377d24debb97398

Could not be applied directly to this PR, since this PR deletes the file.
2022-05-02 11:29:54 +02:00
Rasmus Wriedt Larsen
5f01fc24e4 Merge branch 'main' into promote-xxe 2022-05-02 11:25:55 +02:00
Rasmus Wriedt Larsen
3c1a37e7e1 Merge branch 'main' into new-nosql-examples 2022-05-02 11:21:36 +02:00
Tom Hvitved
29f30a19e7 Merge pull request #8955 from hvitved/csharp/useless-cast-fp
C#: Add FP test for `cs/useless-cast-to-self`
2022-05-02 10:32:28 +02:00
Anders Schack-Mulligen
b2e9555075 Merge pull request #8345 from jorgectf/mybatis-new-sinks
Java: Add `MyBatis`' `Providers` sinks
2022-05-02 09:44:28 +02:00
bananabr
ed58ee86fe documented getSelectionCall 2022-05-01 20:41:43 -05:00
bananabr
57ae07017f adds the Selection API as a new DOM text source 2022-04-30 18:27:31 -05:00
Erik Krogh Kristensen
f87312d4ba have ApiGraphModelsSpecific.qll mention all the required predicates/types 2022-04-30 20:29:44 +02:00
luchua-bc
920a7cd2e6 Put back the taint step removed during merge 2022-04-29 20:29:04 +00:00
Geoffrey White
034c4faf19 Merge branch 'main' into xxe3 2022-04-29 21:06:16 +01:00
Jonathan Leitschuh
c8e0d7f847 Summary model for File should include overriden methods 2022-04-29 14:51:26 -04:00
Henry Mercer
811a2c0053 Merge pull request #8957 from github/henrymercer/upgrade-codeql-action
Use codeql-action/upload-sarif@main in CSV coverage metrics workflow
2022-04-29 17:06:21 +01:00
Arthur Baars
cf4325c86f Add change note 2022-04-29 16:19:11 +02:00
Geoffrey White
614a7650a6 Merge pull request #8775 from porcupineyhairs/cpam
CPP: PAM Authorization Bypass
2022-04-29 14:55:33 +01:00
Jorge
37b051a851 Apply suggestions from code review
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2022-04-29 14:44:17 +02:00
AlexDenisov
5c6e5173ad Merge pull request #8959 from AlexDenisov/alexdenisov/pip-install-from-bazel
Swift: teach bazel to install python dependencies
2022-04-29 14:31:37 +02:00
Paolo Tranquilli
8fc78fae74 Merge pull request #8960 from redsun82/swift-cc-wrappers
Swift: cc wrapper rules
2022-04-29 14:30:54 +02:00
Geoffrey White
812a24fc18 C++: Add test cases for libxml2. 2022-04-29 13:23:29 +01:00
Paolo Tranquilli
2fe38c2bbb Swift: cc wrapper rules 2022-04-29 14:18:36 +02:00
Alex Denisov
7332460268 Swift: teach bazel to install python dependencies 2022-04-29 14:05:36 +02:00
yoff
7efb4ab4e4 Merge pull request #8581 from tausbn/python-fix-bad-join-in-import_star_read
Python: Fix bad join in `import_star_read`
2022-04-29 13:14:14 +02:00
Henry Mercer
d1cc835cad Merge pull request #8949 from github/henrymercer/fix-typo
JS: Nit: Fix typo in QLDoc
2022-04-29 12:04:09 +01:00
Henry Mercer
08b6b1d209 Use codeql-action/upload-sarif@main in CSV coverage metrics workflow 2022-04-29 11:26:32 +01:00
Tom Hvitved
a0e003e33c C#: Add FP test for cs/useless-cast-to-self 2022-04-29 11:59:51 +02:00
Henry Mercer
d3e92f72c4 JS: Nit: Fix typo in QLDoc 2022-04-29 10:54:07 +01:00
Geoffrey White
dd258781ed C++: More test cases. 2022-04-29 10:38:31 +01:00
Geoffrey White
1d71f042db C++: Turns out DOMLSParser is not an AbstractDOMParser and works a little differently than I'd thought. 2022-04-29 10:38:31 +01:00
Geoffrey White
c6deddb290 C++: For consistency. 2022-04-29 10:35:34 +01:00
Geoffrey White
4be3161891 C++: Move some stuff from tests3.cpp to common tests.h 2022-04-29 10:35:34 +01:00
Geoffrey White
397efd1648 C++: Split off the createLSParser tests into their own file. 2022-04-29 10:35:33 +01:00
Geoffrey White
b02519bf0b C++: Make the createLSParser test a bit closer to real life. 2022-04-29 10:33:47 +01:00
Geoffrey White
a1542322e2 C++: Add test cases for SAX2XMLReader. 2022-04-29 10:33:46 +01:00
Erik Krogh Kristensen
080271f14f Merge pull request #8221 from erik-krogh/libProto
JS: recognize more module exports from the factory pattern
2022-04-29 11:23:53 +02:00
Stephan Brandauer
fa377ac763 Merge pull request #8946 from kaeluka/deepFillIn-FN
JS: fix a FN for prototype polluting function query
2022-04-29 10:14:41 +01:00
Erik Krogh Kristensen
b74d1fdb1a Merge pull request #8783 from erik-krogh/jsAbstractBi
JS: don't initialize sanitizer-guards in the standard library
2022-04-29 11:12:16 +02:00
Geoffrey White
7fb1069d69 C++: Use GVN on the values passed into set* functions. 2022-04-29 10:09:52 +01:00
Geoffrey White
215453e4db Update cpp/ql/src/Security/CWE/CWE-611/XXE.ql
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2022-04-29 09:07:25 +01:00
Tony Torralba
9eb6022bbe Merge pull request #8954 from github/workflow/coverage/update
Update CSV framework coverage reports
2022-04-29 10:06:57 +02:00
Geoffrey White
33d499c12d C++: Address review comments. 2022-04-29 09:02:11 +01:00
luchua-bc
0aa1251ffe Add more test cases 2022-04-29 02:31:43 +00:00
github-actions[bot]
1032dcd7e6 Add changed framework coverage reports 2022-04-29 00:15:05 +00:00
jorgectf
548721a8cf Fix MyBatisInjectionSink 2022-04-28 23:36:51 +02:00
Jorge
193ea1a86e Merge branch 'main' into mybatis-new-sinks 2022-04-28 22:26:38 +02:00
Stephan Brandauer
3f13a5e082 fix a FN for prototype polluting function query 2022-04-28 22:00:09 +02:00
Jorge
50e95b5aad Apply suggestions from code review
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2022-04-28 21:56:20 +02:00
Jorge
834f2e845d Delete MyBatisAbstractSql and inline MyBatisAbstractSqlMethodsStep 2022-04-28 21:55:15 +02:00
Chuan-kai Lin
d6f0bbb816 Fix syntax errors in QL comments 2022-04-28 11:53:36 -07:00
AlexDenisov
f6769735e5 Merge pull request #8939 from AlexDenisov/alexdenisov/swift-tracer-integration
Swift: tracer integration
2022-04-28 19:20:55 +02:00
Geoffrey White
79d1ffc1d9 C++: Change note. 2022-04-28 17:49:41 +01:00
Tom Hvitved
3fd93b460f Merge pull request #8935 from hvitved/ruby/typetracker-kw-test 2022-04-28 18:22:51 +02:00
Geoffrey White
2ccd5a5531 C++: Add support for SAXParser in the query. 2022-04-28 16:13:21 +01:00
Geoffrey White
4e2344c488 C++: Add test cases for SAXParser. 2022-04-28 16:11:08 +01:00
Paolo Tranquilli
75265f7c42 Merge pull request #8947 from redsun82/swift-pragma-once
Swift: use `#pragma once`
2022-04-28 16:59:50 +02:00
AlexDenisov
a59d7f6a85 Update swift/extractor/main.cpp 2022-04-28 16:52:34 +02:00
Paolo Tranquilli
c4fae0806f Swift: use #pragma once 2022-04-28 16:39:27 +02:00
AlexDenisov
84bcc2e64a Merge branch 'main' into alexdenisov/swift-tracer-integration 2022-04-28 16:28:48 +02:00
Paolo Tranquilli
2374e6b401 Merge pull request #8934 from redsun82/swift-trapgen
Swift: added trapgen
2022-04-28 16:00:46 +02:00
Jonas Jensen
f1fa7cba5a C++: Remove import order workarounds
These workarounds are no longer needed from CodeQL CLI 2.9.0.
2022-04-28 14:40:57 +02:00
Anders Schack-Mulligen
9d2f386032 Merge pull request #8878 from aschackmull/java/validationmethod-joinorder
Java: Fix join-order.
2022-04-28 14:35:20 +02:00
Tom Hvitved
8d2bf2228b Merge pull request #7914 from hvitved/ruby/generalize-element-content
Ruby: Generalize `ArrayElementContent` to `ElementContent`
2022-04-28 14:23:08 +02:00
Michael Nebel
ec316750d3 Merge pull request #8905 from michaelnebel/csharp/generatedcomment
C#: Add auto generated comment to generated models as data files.
2022-04-28 13:57:38 +02:00
Tom Hvitved
f7669815ce Address review comments 2022-04-28 13:50:26 +02:00
Arthur Baars
ccc18640db Ruby: add upgrade and downgrade scripts 2022-04-28 13:47:14 +02:00
Arthur Baars
d055f9a186 Update tests 2022-04-28 13:47:10 +02:00
Alex Denisov
85918173a6 Swift: ensure the folder for trap files exists 2022-04-28 13:19:25 +02:00
Alex Denisov
9c73ae5a97 Swift: teach extractor to not produce artifacts 2022-04-28 13:18:20 +02:00
Michael Nebel
9d767b8ad8 Merge pull request #8869 from michaelnebel/csharp/frameworkcoverage
C#: Port the java FrameworkCoverage query.
2022-04-28 13:17:50 +02:00
Alex Denisov
5b75b4db79 Swift: add tracer config 2022-04-28 13:17:35 +02:00
Alex Denisov
4a03976a15 Swift: set compiler flags explicitly 2022-04-28 13:17:05 +02:00
Taus
95d235416c Python: Fix bad antijoin in getAKeyword
Before:

```
Tuple counts for Exprs::Call::getAKeyword_dispred#ff#antijoin_rhs/3@7bc202ij after 9s:
1        ~0%     {1} r1 = CONSTANT(unique int)[2]
4244385  ~2%     {1} r2 = JOIN r1 WITH py_dict_items_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'arg0'
4244352  ~3%     {3} r3 = JOIN r2 WITH AstGenerated::Call_::getNamedArg_dispred#ffb_201#join_rhs ON FIRST 1 OUTPUT Rhs.1 'arg1', Lhs.0 'arg0', Rhs.2 'arg2'
66618690 ~3%     {5} r4 = JOIN r3 WITH AstGenerated::Call_::getNamedArg_dispred#ffb ON FIRST 1 OUTPUT Lhs.1 'arg0', Lhs.0 'arg1', Lhs.2 'arg2', Rhs.1, Rhs.2
31187133 ~0%     {5} r5 = SELECT r4 ON In.3 < In.2 'arg2'
31187133 ~1%     {5} r6 = SCAN r5 OUTPUT In.4, 0, In.0 'arg0', In.1 'arg1', In.2 'arg2'
0        ~0%     {3} r7 = JOIN r6 WITH py_dict_items ON FIRST 2 OUTPUT Lhs.2 'arg0', Lhs.3 'arg1', Lhs.4 'arg2'
                 return r7

Tuple counts for Exprs::Call::getAKeyword_dispred#ff/2@1dc9468b after 421ms:
1       ~0%     {1} r1 = CONSTANT(unique int)[2]
4244385 ~2%     {1} r2 = JOIN r1 WITH py_dict_items_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'result'
4244352 ~0%     {3} r3 = JOIN r2 WITH AstGenerated::Call_::getNamedArg_dispred#ffb_201#join_rhs ON FIRST 1 OUTPUT Lhs.0 'result', Rhs.1 'this', Rhs.2
4244352 ~0%     {3} r4 = r3 AND NOT Exprs::Call::getAKeyword_dispred#ff#antijoin_rhs(Lhs.0 'result', Lhs.1 'this', Lhs.2)
4244352 ~6%     {2} r5 = SCAN r4 OUTPUT In.1 'this', In.0 'result'
                return r5
```

Oof. All that work to produce zero tuples. Luckily we can improve
matters somewhat.

Basically, there's no reason to test _all_ dictionary unpackings, since
we're only interested in a lower bound. Thus, we can use `min` instead
which is much more efficient. For convenience I factored this into its
own (private) helper predicate.

Now the tuple counts look as follows:

```
Tuple counts for Exprs::Call::getMinimumUnpackingIndex_dispred#ff#min_range/2@39b0e9sm after 1ms:
246 ~0%     {2} r1 = JOIN Keywords::DictUnpackingOrKeyword#class#f#shared WITH AstGenerated::Call_::getNamedArg_dispred#ffb_201#join_rhs ON FIRST 1 OUTPUT Rhs.1 'arg0', Rhs.2 'arg1'
            return r1
Registering Exprs::Call::getMinimumUnpackingIndex_dispred#ff#min_range/2@39b0e9sm +  with content 9ea2f123k8necpu015v6tpsc2t1
 >>> Created relation Exprs::Call::getMinimumUnpackingIndex_dispred#ff#min_range/2@39b0e9sm with 246 rows.
Starting to evaluate predicate Exprs::Call::getMinimumUnpackingIndex_dispred#ff#min_term/3@9f4ca5g8
Tuple counts for Exprs::Call::getMinimumUnpackingIndex_dispred#ff#min_term/3@9f4ca5g8 after 0ms:
246 ~2%     {3} r1 = JOIN Keywords::DictUnpackingOrKeyword#class#f#shared WITH AstGenerated::Call_::getNamedArg_dispred#ffb_201#join_rhs ON FIRST 1 OUTPUT Rhs.1 'arg0', Rhs.2 'arg2', Rhs.2 'arg2'
            return r1

Tuple counts for Exprs::Call::getAKeyword_dispred#ff/2@000a0alb after 906ms:
1       ~0%     {1} r1 = CONSTANT(unique int)[2]
4244385 ~2%     {1} r2 = JOIN r1 WITH py_dict_items_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'result'

4244352 ~0%     {3} r3 = JOIN r2 WITH AstGenerated::Call_::getNamedArg_dispred#ffb_201#join_rhs ON FIRST 1 OUTPUT Lhs.0 'result', Rhs.1 'this', Rhs.2
4244280 ~0%     {3} r4 = r3 AND NOT Exprs::Call::getMinimumUnpackingIndex_dispred#ff_0#antijoin_rhs(Lhs.1 'this')
4244280 ~6%     {2} r5 = SCAN r4 OUTPUT In.1 'this', In.0 'result'

4244352 ~3%     {3} r6 = JOIN r2 WITH AstGenerated::Call_::getNamedArg_dispred#ffb_201#join_rhs ON FIRST 1 OUTPUT Rhs.1 'this', Lhs.0 'result', Rhs.2
72      ~4%     {4} r7 = JOIN r6 WITH Exprs::Call::getMinimumUnpackingIndex_dispred#ff ON FIRST 1 OUTPUT Lhs.1 'result', Lhs.0 'this', Lhs.2, Rhs.1
72      ~4%     {4} r8 = SELECT r7 ON In.2 <= In.3
72      ~0%     {2} r9 = SCAN r8 OUTPUT In.1 'this', In.0 'result'

4244352 ~6%     {2} r10 = r5 UNION r9
                return r10
```

This is not the perfect join order (note the similarity between `r3`
and `r6`) but overall it's a win.
2022-04-28 11:11:37 +00:00
Taus
80ef09f034 Python: Fix bad join in declaredAttributeVar
Before:
```
Tuple counts for PointsTo::declaredAttributeVar#fbf/3@99d5aenq after 1.1s:
451054   ~7%     {2} r1 = SCAN variable OUTPUT In.0, In.2 'name'
1296149  ~0%     {2} r2 = JOIN r1 WITH Essa::EssaVariable::getSourceVariable_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'var', Lhs.1 'name'
12179900 ~4%     {3} r3 = JOIN r2 WITH Essa::EssaVariable::getAUse_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'name', Lhs.0 'var'
8028     ~2%     {3} r4 = JOIN r3 WITH Scope::Scope::getANormalExit_dispred#bf_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'name', Lhs.2 'var'
8028     ~2%     {3} r5 = JOIN r4 WITH Classes::PythonClassObjectInternal::getScope_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'cls', Lhs.1 'name', Lhs.2 'var'
                 return r5
```

After:
```
Tuple counts for PointsTo::declaredAttributeVar#fbf/3@cccf36hb after 4ms:
1450 ~0%     {2} r1 = SCAN Classes::PythonClassObjectInternal::getScope_dispred#ff OUTPUT In.1, In.0 'cls'
1450 ~7%     {2} r2 = JOIN r1 WITH Scope::Scope::getANormalExit_dispred#bf ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'cls'
8028 ~0%     {2} r3 = JOIN r2 WITH Essa::EssaVariable::getAUse_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'var', Lhs.1 'cls'
8028 ~0%     {3} r4 = JOIN r3 WITH Essa::EssaVariable::getSourceVariable_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'cls', Lhs.0 'var'
8028 ~2%     {3} r5 = JOIN r4 WITH variable ON FIRST 1 OUTPUT Lhs.1 'cls', Rhs.2 'name', Lhs.2 'var'
return r5
```
2022-04-28 11:11:37 +00:00
Taus
d28f9f41e8 Python: Fix bad join in import_star_read
Makes this

```
(21s) Tuple counts for DataFlowPublic::import_star_read#ff/2@fcd5e6nr after 8.5s:
9743      ~6%     {3} r1 = SCAN num#DataFlowPublic::TModuleVariableNode#fff OUTPUT In.1, In.0, In.2 'result'
9743      ~1%     {3} r2 = JOIN r1 WITH Variables::Variable::getId_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2 'result'
390808917 ~3%     {3} r3 = JOIN r2 WITH Flow::NameNode::getId_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2 'result'
307       ~0%     {2} r4 = JOIN r3 WITH ImportStar::ImportStar::importStarResolvesTo#ff ON FIRST 2 OUTPUT Lhs.0, Lhs.2 'result'
307       ~0%     {2} r5 = JOIN r4 WITH num#DataFlowPublic::TCfgNode#ff ON FIRST 1 OUTPUT Rhs.1 'n', Lhs.1 'result'
                  return r5
```

become this

```
(17s) Tuple counts for DataFlowPublic::resolved_import_star_module#fff/3@f5e84aic after 0ms:
307 ~0%     {3} r1 = JOIN ImportStar::ImportStar::importStarResolvesTo#ff WITH num#DataFlowPublic::TCfgNode#ff ON FIRST 1 OUTPUT Lhs.0, Lhs.1 'm', Rhs.1 'n'
307 ~0%     {3} r2 = JOIN r1 WITH Flow::NameNode::getId_dispred#ff ON FIRST 1 OUTPUT Lhs.1 'm', Rhs.1 'name', Lhs.2 'n'
            return r2
(17s) Registering DataFlowPublic::resolved_import_star_module#fff/3@f5e84aic +  with content f29281ig38r98icro4ege09mrva
(17s)  >>> Created relation DataFlowPublic::resolved_import_star_module#fff/3@f5e84aic with 307 rows.
(17s) Starting to evaluate predicate DataFlowPublic::import_star_read#ff/2@57b0c06e
(17s) Tuple counts for DataFlowPublic::import_star_read#ff/2@57b0c06e after 2ms:
9743 ~0%     {3} r1 = SCAN num#DataFlowPublic::TModuleVariableNode#fff OUTPUT In.1, In.0, In.2 'result'
9743 ~0%     {3} r2 = JOIN r1 WITH Variables::Variable::getId_dispred#ff ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.2 'result'
307  ~0%     {2} r3 = JOIN r2 WITH DataFlowPublic::resolved_import_star_module#fff ON FIRST 2 OUTPUT Rhs.2 'n', Lhs.2 'result'
             return r3
```
2022-04-28 11:11:37 +00:00
Arthur Baars
20a3e3a8ae Update library 2022-04-28 13:00:02 +02:00
Arthur Baars
65989ae564 Update dbscheme stats 2022-04-28 13:00:02 +02:00
Arthur Baars
a848929069 Regenerate QLL library 2022-04-28 13:00:02 +02:00
Arthur Baars
0d9354322e Update tree-sitter-ruby 2022-04-28 13:00:02 +02:00
Arthur Baars
7359ffaa2e Ruby: add tree-sitter test case 2022-04-28 12:59:56 +02:00
Paolo Tranquilli
773ef62406 Swift: added trapgen
This checks in the trapgen script generating trap entries in C++.

The codegen suite has been slightly reorganized, moving the templates
directory up one level and chopping everything into smaller bazel
packages. Running tests is now done via
```
bazel run //swift/codegen/test
```

With respect to the PoC, the nested `codeql::trap` namespace has been
dropped in favour of a `Trap` prefix (or suffix in case of entries)
within the `codeql` namespace. Also, generated C++ code is not checked
in in git any more, and generated during build. Finally, labels get
printed in hex in the trap file.

`TrapLabel` is for the moment only default-constructible, so only one
single label is possible. `TrapArena`, that is responsible for creating
disjoint labels will come in a later commit.
2022-04-28 12:01:59 +02:00
Michael Nebel
150d9ba52c Update .github/workflows/csv-coverage-metrics.yml
Co-authored-by: Henry Mercer <henry.mercer@me.com>
2022-04-28 11:57:53 +02:00
Tom Hvitved
29f1c533a9 Ruby: Add type tracker tests for flow through keyword/positional parameters 2022-04-28 11:34:12 +02:00
Michael Nebel
c606121ae7 C#: Move autogenerated comment to file level instead of having it on each class. 2022-04-28 11:27:49 +02:00
Michael Nebel
57fc4d987f C#: Fix indentation. 2022-04-28 11:19:54 +02:00
Michael Nebel
583b9b61de C#: Add job for running the framework coverage query for C#. 2022-04-28 11:19:49 +02:00
Michael Nebel
98b2bc06ce C#: Port the java FrameworkCoverage query. 2022-04-28 11:18:12 +02:00
Jonas Jensen
0c65e67d18 QL language reference: variables must be lowerId
To prepare for a future QL language change where variable names must
start with a lower-case letter, this commit updates the QL language
reference (including the language specification) to change the variable
name grammar from `simpleId` to `lowerId`.
2022-04-28 09:13:36 +02:00
luchua-bc
590b9d8519 Standardize the query and update qldoc 2022-04-27 22:17:17 +00:00
Taus
b4a31e572f Python: Add global attribute writes 2022-04-27 16:45:00 +00:00
Taus
f71cf2e1fc Python: Add test 2022-04-27 15:48:11 +00:00
Tony Torralba
e99cee4913 Merge branch 'main' into java/unsafe-get-resource 2022-04-27 16:45:42 +02:00
Michael Nebel
52b59d0eed C#: Add auto generated comment to generated models as data files. 2022-04-27 15:40:23 +02:00
Tom Hvitved
790d97714f Ruby: Replace Element with Element[any]
To make it look more like `Argument` tokens.
2022-04-27 11:53:25 +02:00
Tom Hvitved
d1c9d68e14 Ruby: Generalize ArrayElementContent to ElementContent 2022-04-27 11:53:21 +02:00
Jonathan Leitschuh
2565cdb964 Add additional File taint value flow models
Adds
 - File::getAbsoluteFile
 - File::getCanonicalFile
 - File::getAbsolutePath
 - File::getCanonicalPath
2022-04-26 10:42:53 -04:00
Anders Schack-Mulligen
ff1c6ca4d6 Java: Fix join-order. 2022-04-26 13:43:41 +02:00
Tony Torralba
2ee83e2ba2 Add Editable.toString flow step 2022-04-26 13:34:16 +02:00
James Fletcher
5a7043f528 Update analyzing-databases-with-the-codeql-cli.rst 2022-04-25 15:57:18 +01:00
Erik Krogh Kristensen
0a26e891a2 include startsWith/endsWith checks in js/missing-origin-check 2022-04-25 15:28:50 +02:00
Erik Krogh Kristensen
fe3d71ebc2 fix qhelp: the window, not the origin, is sending the message
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
2022-04-25 14:07:01 +02:00
Erik Krogh Kristensen
b5193d99d7 have getSourceType() depend on which kind of event it is 2022-04-25 11:32:52 +02:00
Erik Krogh Kristensen
3b0066e93d address review comments 2022-04-22 14:01:24 +02:00
Geoffrey White
40da7a1055 C++: Add a test of NoCheckBeforeUnsafePutUser.ql. 2022-04-21 16:55:50 +01:00
Erik Krogh Kristensen
c1798c4ebd remove redundant extends clause 2022-04-21 09:13:18 +02:00
Erik Krogh Kristensen
6007dfa101 fix qldoc in StoredXssCustomizations
Co-authored-by: Asger F <asgerf@github.com>
2022-04-21 09:11:08 +02:00
Erik Krogh Kristensen
b9a7c563d1 fix typo in change note
Co-authored-by: Asger F <asgerf@github.com>
2022-04-21 09:09:56 +02:00
Erik Krogh Kristensen
7e73ecceab add change-note 2022-04-20 23:31:42 +02:00
Porcupiney Hairs
06edb3f3a1 fix formatting issues 2022-04-21 00:23:49 +05:30
Erik Krogh Kristensen
06394c8dc6 move storedXss sources to the Customizations file 2022-04-20 18:17:49 +02:00
Erik Krogh Kristensen
58fcdbc406 QL: remove some benign results from ql/abstract-class-import 2022-04-20 18:17:08 +02:00
Erik Krogh Kristensen
81ce8ac715 ATM: fix compiler warnings about unused variables 2022-04-20 18:10:59 +02:00
Erik Krogh Kristensen
4bc36d82f6 update expected output for ATM 2022-04-20 18:10:56 +02:00
Erik Krogh Kristensen
c1c66a0200 refactor CountAlertAndEndpoints to not refer to deprecated files 2022-04-20 18:10:56 +02:00
Erik Krogh Kristensen
c5f7df17ee add .actual files to .gitignore for ATM tests 2022-04-20 18:10:56 +02:00
Erik Krogh Kristensen
1c5d59f885 fix an instance of ql/acronyms-should-be-pascal-case 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
ea6b68fc59 add missing qldoc 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
12e60c7a06 move TypeTestGuard to the Query.qll file 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
b1bad271d5 only activate the PrefixString label in Query.qll files 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
8a5b1668f9 move initialization of sanitizer-guards to Query.qll files 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
73dbe44824 remove dead import 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
8d3bd9d7cd move the ExceptionXss sources into the Customizations file 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
25708c5091 move the XssThroughDom sources into the Customizations file 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
ad14bbae90 create a customizations file for StoredXss 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
162a4992a5 move the ReflectedXss sources/sinks into the Customizations file 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
173e1d0262 move the DomBasedXss sources/sinks into the Customizations file 2022-04-20 18:10:53 +02:00
Erik Krogh Kristensen
9631b68de9 move LocalUrlSanitizingGuard out of the customizations file 2022-04-20 18:10:52 +02:00
Rasmus Wriedt Larsen
bb6969a175 Merge branch 'main' into promote-xxe 2022-04-20 13:42:02 +02:00
Rasmus Wriedt Larsen
888a38c060 Python: Add change-note 2022-04-20 11:46:09 +02:00
Rasmus Wriedt Larsen
d70f247001 Python: More private import python 2022-04-20 11:42:13 +02:00
Rasmus Wriedt Larsen
084c8eb22e Python: Don't re-export python under DataFlow:: 2022-04-20 11:42:10 +02:00
Rasmus Wriedt Larsen
5dbbd17bb2 Python: Add test to ensure we keep DataFlow imports clean
Currently we're not in a good state :(
2022-04-20 11:41:01 +02:00
luchua-bc
b76873fc8d Add more test cases 2022-04-19 22:22:15 +00:00
luchua-bc
f0c4b1955b Change getResource() to be a taint step 2022-04-19 15:55:09 +00:00
Porcupiney Hairs
85c751cb7f CPP: PAM Authorization Bypass
This PR is similar to my other PRs for
[Python](https://github.com/github/codeql/pull/8595) and
[Golang](https://github.com/github/codeql-go/pull/709).

This PR aims to detect instances were an initiated PAM Transaction invokes the `pam_authenticate` method but does not invoke a call to the pam_acct_mgmt` method. This is bad as a call to `pam_authenticate` only verifies the users credentials. It does not check if the user account is still is a valid state.

If only a call to `pam_authenticate` is used to verify the user, a user with an expired account password would still be able to login. This can be prevented by calling the `pam_acct_mgmt` function after a `pam_authenticate` function.
2022-04-19 18:24:19 +05:30
Erik Krogh Kristensen
e0b5197d3c a slight refactor 2022-04-18 22:21:41 +02:00
Erik Krogh Kristensen
7f592a6c64 merge Clipboard.qll and DragAndDrop.qll, and support InputEvent 2022-04-18 22:17:31 +02:00
jorgectf
9e1b98e5a4 Detach MyBatisAbstractSqlMethodsStep from MyBatisAbstractSql 2022-04-15 13:08:04 +02:00
Rasmus Wriedt Larsen
6235dc5039 Python: Handle find_library assignment to temp variable 2022-04-13 11:44:15 +02:00
Rasmus Wriedt Larsen
c87b3087be Python: Add test for Django FileField upload_to
The output from running the test script is:

```
'rootdir/bar'
[13/Apr/2022 09:20:36] "POST /app/file-test/ HTTP/1.1" 200 2
'rootdir/bar'
[13/Apr/2022 09:20:36] "POST /app/file-test/ HTTP/1.1" 200 2
'rootdir/foo%2fbar'
[13/Apr/2022 09:20:36] "POST /app/file-test/ HTTP/1.1" 200 2
'rootdir/%2e%2e%2fbar'
[13/Apr/2022 09:20:36] "POST /app/file-test/ HTTP/1.1" 200 2
'rootdir/foo%c0%afbar'
[13/Apr/2022 09:20:36] "POST /app/file-test/ HTTP/1.1" 200 2
```

I didn't add a `.py` extension, so it wasn't extracted, since we don't
actually care about what we model in that file.
2022-04-13 11:27:18 +02:00
Rasmus Wriedt Larsen
304713ca87 Python: Handle django v4 as well in tests 2022-04-13 11:21:44 +02:00
Rasmus Wriedt Larsen
bdadf2b445 Python: Fix warnings 2022-04-13 10:30:59 +02:00
Rasmus Wriedt Larsen
4927f0018b Merge branch 'main' into django-filefield-uploadto 2022-04-13 10:22:28 +02:00
Porcupiney Hairs
785dc1af3c Include changes from review 2022-04-12 21:17:39 +05:30
Erik Krogh Kristensen
df295e69d6 add change-note 2022-04-12 14:37:51 +02:00
Erik Krogh Kristensen
bca4d14129 rename files 2022-04-12 14:37:43 +02:00
Erik Krogh Kristensen
591fcda862 various improvements to the js/missing-origin-verification query 2022-04-12 14:20:41 +02:00
Erik Krogh Kristensen
2d6d304d7c add InclusionTest to PostMessageEventSanitizer 2022-04-12 14:12:36 +02:00
Erik Krogh Kristensen
e2badab251 update expected output after test reorganization 2022-04-12 10:39:28 +02:00
Erik Krogh Kristensen
ec9c308d06 reorganize the tests in CWE-020 2022-04-12 10:39:28 +02:00
Erik Krogh Kristensen
18532bae54 move js/missing-postmessageorigin-verification out of experimental 2022-04-12 10:39:27 +02:00
Erik Krogh Kristensen
34abef8a6c Merge branch 'main' into dragAndDrop 2022-04-11 23:59:46 +02:00
bananabr
57fac949fd included ClipboardEvent and DragEvent as XSS sources 2022-04-11 16:37:00 -05:00
luchua-bc
7029802f3b Add sinks for getClass() and getClassLoader() 2022-04-11 21:03:48 +00:00
Erik Krogh Kristensen
aafa8ddc9f add support for domNode.onpaste for copy-paste events 2022-04-11 20:10:56 +02:00
Erik Krogh Kristensen
6713b2c671 add support for domNode.ondrop for drag-and-drop events 2022-04-11 20:06:12 +02:00
bananabr
121aad7fd2 updated change notes 2022-04-11 12:45:37 -05:00
Marcono1234
bc5dc6ad50 Java: Remove TODO comment for getRuleExpression() behavior
Predicate behavior has been fixed on `main`.
2022-04-10 18:24:26 +02:00
Marcono1234
7bed14bbf0 Merge remote-tracking branch 'remotes/origin/main' into marcono1234/statement-expression 2022-04-10 18:23:45 +02:00
bananabr
0f1582f3f6 included JavaScript drag and drop API Xss sources 2022-04-09 22:33:30 -05:00
luchua-bc
eccd97c7b7 Query to detect unsafe getResource calls in Java EE applications 2022-04-09 01:14:15 +00:00
Rasmus Wriedt Larsen
517444b5ff Python: Fix SimpleXmlRpcServer.expected 2022-04-07 16:42:40 +02:00
Rasmus Wriedt Larsen
ec66f26ade Python: Handle get_collection on pymongo DB 2022-04-07 16:32:20 +02:00
Rasmus Wriedt Larsen
89eeaf85d5 Python: Handle get_database on MongoClient instance 2022-04-07 16:31:17 +02:00
Rasmus Wriedt Larsen
7ca19653df Python: mongoDBInstance refactor 2022-04-07 16:22:57 +02:00
Rasmus Wriedt Larsen
e58e9a273b Python: mongoClientInstance refactoring 2022-04-07 16:22:16 +02:00
Rasmus Wriedt Larsen
0ce2ced1aa Python: Model pymongo.mongo_client.MongoClient 2022-04-07 16:22:16 +02:00
Rasmus Wriedt Larsen
81fdc1bd78 Python: Add more pymongo NoSQL tests 2022-04-07 16:22:16 +02:00
Rasmus Wriedt Larsen
30fff1cf8b Python: Merge pymongo NoSQL tests 2022-04-07 16:04:25 +02:00
Rasmus Wriedt Larsen
8191be9d75 Python: Move last XXE/XML bomb out of experimental 2022-04-07 15:37:56 +02:00
Rasmus Wriedt Larsen
405480c410 Python: Rename sink definitions for XXE/XML bomb 2022-04-07 15:37:56 +02:00
Rasmus Wriedt Larsen
7728b6cf1b Python: Change XmlBomb vulnerability kind 2022-04-07 10:56:35 +02:00
Rasmus Wriedt Larsen
f2f0873d91 Python: Use new API::CallNode for XML constant check
This also means that the detection of the values passed to these keyword
arguments will no longer just be from a local scope, but can also be
across function boundaries.
2022-04-06 15:49:06 +02:00
Rasmus Wriedt Larsen
c784f15762 Python: Rename more XML classes to follow convention
- `XMLEtree` to `XmlEtree`
- `XMLSax` to `XmlSax`
- `LXML` to `Lxml`
- `XMLParser` to `XmlParser`
2022-04-06 15:44:54 +02:00
Rasmus Wriedt Larsen
23637fd691 Merge branch 'main' into promote-xxe 2022-04-06 12:56:31 +02:00
ihsinme
275b29a288 Update DangerousUseOfExceptionBlocks.expected 2022-04-05 22:48:11 +03:00
Rasmus Wriedt Larsen
b7f56dd17e Python: Rewrite concepts to use extends ... instanceof ...
This caused compilation time for `ConceptsTest.ql` to go from 1m24s to
7s
2022-04-05 12:31:09 +02:00
Rasmus Wriedt Larsen
a7dab53ed2 Python: Add change-note 2022-04-05 11:46:49 +02:00
Rasmus Wriedt Larsen
1f285b8983 Python: Rename to XmlParsingVulnerabilityKind
To keep up with style guide
2022-04-05 11:07:12 +02:00
Rasmus Wriedt Larsen
ab59d5c786 Python: Rename to XmlParsing
To follow our style guide
2022-04-05 11:06:22 +02:00
ihsinme
73de757f39 Update DangerousUseOfExceptionBlocks.ql 2022-04-04 21:38:03 +03:00
ihsinme
61860c9ae9 Update DangerousUseOfExceptionBlocks.ql 2022-04-02 13:44:40 +03:00
Rasmus Wriedt Larsen
d2b03bb480 Python: Fix SimpleXmlRpcServer.ql 2022-03-31 20:37:28 +02:00
Rasmus Wriedt Larsen
4abab22066 Python: Promote XXE and XML-bomb queries
Need to write a change-note as well, but will do that tomorrow
2022-03-31 18:47:50 +02:00
Rasmus Wriedt Larsen
b8d3c5e96f Python: Remove last bits of experimental XML modeling 2022-03-31 18:40:26 +02:00
Rasmus Wriedt Larsen
5083023aa8 Python: Move XML parsing PoC
Since the folder where it used to live is now empty otherwise :O
2022-03-31 18:37:47 +02:00
Rasmus Wriedt Larsen
673220b231 Python: Minor cleanup of XmlParsingTest 2022-03-31 18:18:35 +02:00
Rasmus Wriedt Larsen
b4c0065aeb Python: Extend FileSystemAccess for xml.sax and xml.dom.* parsing 2022-03-31 18:08:47 +02:00
Rasmus Wriedt Larsen
1d7cec60ae Python: xml.sax.parse is not a method call
And it's not possible to provide a parser argument either
2022-03-31 17:50:23 +02:00
Rasmus Wriedt Larsen
e11269715d Python: Promote xml.sax and xml.dom.* modeling 2022-03-31 17:44:00 +02:00
Rasmus Wriedt Larsen
05bb0ef976 Python: Align xml.etree.ElementTree modeling
I didn't find a good way to actually share the stuff, so we kinda just
have 2 things that look very similar :|
2022-03-31 17:24:16 +02:00
Rasmus Wriedt Larsen
70b3eecdd5 Python: Merge xml.etree.ElementTree models
I forgot about the existing ones when I promoted it
2022-03-31 17:13:11 +02:00
Rasmus Wriedt Larsen
db43d043c4 Python: Add test showing misalignment of xml.etree modeling 2022-03-31 11:55:46 +02:00
Rasmus Wriedt Larsen
543454eff2 Python: Model file access from XML parsing 2022-03-31 11:47:29 +02:00
Rasmus Wriedt Larsen
386ff53614 Python: Model lxml.iterparse 2022-03-31 11:32:22 +02:00
Rasmus Wriedt Larsen
12cbdcde28 Python: Model lxml.etree.XMLID 2022-03-31 11:21:24 +02:00
Rasmus Wriedt Larsen
6774085e7a Python: Add note about parseid/XMLID 2022-03-31 11:19:25 +02:00
Rasmus Wriedt Larsen
a315aa84b2 Python: Add some links in QLDocs 2022-03-31 11:16:50 +02:00
Rasmus Wriedt Larsen
64aa503cc3 Python: Promote xml.etree modeling 2022-03-31 11:12:02 +02:00
Rasmus Wriedt Larsen
7f5f7679f8 Python: Promote xmltodict modeling 2022-03-31 10:28:34 +02:00
Rasmus Wriedt Larsen
80b5cde3a2 Python: Promote lxml parsing modeling 2022-03-31 10:19:08 +02:00
Rasmus Wriedt Larsen
3040adfd9b Python: Handle XMLParser().close() for XPath 2022-03-31 10:08:26 +02:00
Rasmus Wriedt Larsen
c4473c5f65 Python: Rename lxml XPath tests 2022-03-31 10:08:02 +02:00
Rasmus Wriedt Larsen
1ea4bcc59f Python: Make XMLParsing a Decoding subclass 2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
35ccba2ec1 Python: Promote XMLParsing concept test 2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
e45288e812 Python: => XMLParsingVulnerabilityKind
Since there are other XML vulnerabilities that are not about parsing,
this is more correct.
2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
e005a5c0ab Python: Promote XMLParsing concept 2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
9caf4be21b Python: Add PortSwigger link to Xxe.qhelp
I found this resource quite good myself at least :)
2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
56b9c891d8 Python: Adjust XmlBomb.qhelp from JS 2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
b00766b054 Python: Adjust XXE qhelp
and remove the old copy, we don't need it anymore :)
2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
c365337867 Python: Delete XmlEntityInjection.ql
Kept the test of SimpleXmlRpcServer, and kept the qhelp so it can be
used to write the new qhelp files
2022-03-31 09:52:55 +02:00
Rasmus Wriedt Larsen
769f5691d0 Python: Add taint for StringIO and BytesIO 2022-03-31 09:52:54 +02:00
Rasmus Wriedt Larsen
57b9780428 Python: XXE: Add example of exfiltrating data through dtd-retrival 2022-03-31 09:52:54 +02:00
Rasmus Wriedt Larsen
a1d88e39a7 Python: Adjust XXE PoC for newer lxml versions
Which doesn't raise that syntax error (at least not on my laptop)
2022-03-31 09:52:54 +02:00
Rasmus Wriedt Larsen
91795b8577 Python: Add simple test of Xxe/XmlBomb
Note that most of the testing happens in the framework specific tests,
with an inline-expectation test
2022-03-31 09:52:54 +02:00
Rasmus Wriedt Larsen
e45f9d69cc Python: Adjust Xxe/XmlBomb for Python
I changed a few QLdocs so they fit the style we have used in Python...
although I surely do regret having introduced a new style for how these
QLDocs look :D
2022-03-31 09:52:54 +02:00
Rasmus Wriedt Larsen
65907c9762 Python: Copy Xxe/XmlBomb queries from JS
After internal discussion, these will replace the `XmlEntityInjection`
query, so we can have separate severities on DoS and the other (more
serious) attacks.

Note: These clearly don't work, since they are verbatim copies of the JS
code, but I split it into multiple commits to clearly highlight what
changes were made.
2022-03-31 09:52:54 +02:00
ihsinme
b95094235c Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2022-03-30 10:51:38 +03:00
Porcupiney Hairs
92033047a5 Python : Add query to detect PAM authorization bypass
Using only a call to `pam_authenticate` to check the validity of a login can
lead to authorization bypass vulnerabilities. A `pam_authenticate` only
verifies the credentials of a user. It does not check if a user has an
appropriate authorization to actually login. This means a user with a
expired login or a password can still access the system.

This PR includes a qhelp describing the issue, a query which detects instances where a call to
`pam_acc_mgmt` does not follow a call to `pam_authenticate` and it's
corresponding tests.

This PR has multiple detections. Some of the public one I can find are :
* [CVE-2022-0860](https://nvd.nist.gov/vuln/detail/CVE-2022-0860) found
in [cobbler/cobbler](https://www.github.com/cobbler/cobbler)
* [fredhutch/motuz](https://www.huntr.dev/bounties/d46f91ca-b8ef-4b67-a79a-2420c4c6d52b/)
2022-03-30 00:47:58 +05:30
yoff
3416f074e8 Update python/ql/src/Security/CWE-352/CSRFProtectionDisabled.ql
Explain why `TestScope` is not used.

Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2022-03-29 13:59:04 +02:00
Rasmus Lerchedahl Petersen
d39410aa2d python: backport review comment to Ruby 2022-03-28 07:35:14 +02:00
Rasmus Lerchedahl Petersen
774c811e97 python: move CSRF concepts inside HTTP::Server 2022-03-28 07:35:13 +02:00
Marcono1234
f19ade3446 Java: Add StmtExpr 2022-03-27 01:42:34 +01:00
Rasmus Lerchedahl Petersen
1e9840d779 python: broaden local protection concept 2022-03-25 12:28:33 +01:00
Rasmus Lerchedahl Petersen
179f77b123 python: clearer comment 2022-03-25 11:51:24 +01:00
Rasmus Lerchedahl Petersen
778a88f32c python: update qhelp
removing custom middleware stack
will _not_ enable CSRF protection
2022-03-25 11:49:06 +01:00
yoff
85f1d92a0d Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2022-03-25 11:42:32 +01:00
Erik Krogh Kristensen
47a9376e81 fix bad join in js/unreachable-method-overloads 2022-03-24 16:09:10 +01:00
Rasmus Lerchedahl Petersen
ce017394e6 python: fix change note (hepofully) 2022-03-24 12:01:46 +01:00
Rasmus Lerchedahl Petersen
aecf4e48f8 python: add change note 2022-03-24 11:43:07 +01:00
Rasmus Lerchedahl Petersen
93336bcb16 python: allow alternative middleware
(observed [on LGTM](9d6a7ee180/files/mozillians/settings.py (L96)))
2022-03-23 12:27:51 +01:00
Rasmus Lerchedahl Petersen
6c2449564a python: add concept tests 2022-03-23 12:05:09 +01:00
Rasmus Lerchedahl Petersen
441e206cfa python: CSRF -> Csrf 2022-03-23 11:29:27 +01:00
Rasmus Lerchedahl Petersen
53de8287f5 python: rule out test code for CSRF 2022-03-22 14:57:05 +01:00
Rasmus Lerchedahl Petersen
0f2c21c8bd python: require local protection to be absent
for CSRF to be likely
2022-03-22 13:42:52 +01:00
Rasmus Lerchedahl Petersen
f5b53083ae python: require authentication middleware
for CSRF to be relevant
2022-03-22 08:44:19 +01:00
ihsinme
151c93f502 Update DangerousUseOfExceptionBlocks.cpp 2022-03-21 09:52:14 +03:00
ihsinme
22cf3f7b20 Update test.cpp 2022-03-21 09:50:30 +03:00
Tony Torralba
8790df7a34 Style fixes 2022-03-16 15:11:04 +01:00
jorgectf
f6eb83fd22 Update MyBatisAnnotationSqlInjection.qlref
By adding more imports in the test file, the expected result's lines changed.
2022-03-16 10:12:38 +01:00
ihsinme
ccbb4434de Update DangerousUseOfExceptionBlocks.expected 2022-03-16 09:54:35 +03:00
ihsinme
cd561dd19c Update test.cpp 2022-03-16 09:53:45 +03:00
ihsinme
2959150198 Update DangerousUseOfExceptionBlocks.ql 2022-03-16 09:30:38 +03:00
jorgectf
e0952ba432 Fix change note
Thanks @atorralba!
2022-03-15 16:41:32 +01:00
jorgectf
3356bc4085 Add change note 2022-03-15 16:26:34 +01:00
jorgectf
ed198709b4 Refactor MyBatisAbstractSQLMethodsStep
Set output to `Argument[-1]` instead of `ReturnValue` to be able to get rid of `MyBatisAbstractSQLAnonymousClassStep`.

Thanks @pwntester!
2022-03-15 13:46:06 +01:00
jorgectf
9aa440e5b6 Refactor MyBatisAbstractSQLMethodsStep and MyBatisAbstractSQLMethod
See https://github.com/github/codeql/pull/8345\#discussion_r826734537
2022-03-15 13:23:23 +01:00
ihsinme
62ecf54aaa Update DangerousUseOfExceptionBlocks.cpp 2022-03-15 08:53:38 +03:00
ihsinme
e99eaeb256 Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2022-03-15 08:53:00 +03:00
jorgectf
f10dac31f9 Format some tests 2022-03-14 22:12:22 +01:00
jorgectf
b62b8c8d28 Use SummaryModelCsv for the toString taint step 2022-03-14 21:47:06 +01:00
jorgectf
c683b48af7 Add MyBatisInjectionSink's QLDoc 2022-03-14 21:41:36 +01:00
jorgectf
8482c01959 Make MyBatisProviderStep an AdditionalValueStep 2022-03-14 21:35:26 +01:00
jorgectf
32f494eba1 Use SummaryModelCsv in MyBatisAbstractSQLMethodsStep 2022-03-14 21:32:55 +01:00
jorgectf
d47fcedd21 Add tests 2022-03-14 21:31:51 +01:00
Jorge
158366ab46 Apply suggestions from code review
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2022-03-14 21:27:37 +01:00
jorgectf
a0bf68f7cd Generally extend TaintTracking::AdditionalTaintStep 2022-03-14 13:39:20 +01:00
jorgectf
ded9663f2b Finish taint steps 2022-03-13 13:59:03 +01:00
jorgectf
447636bf1c Attempt to add MyBatis' sinks and taint steps to SQL and OGNL injection queries 2022-03-09 04:21:26 +01:00
jorgectf
e000163614 Properly model AbstractSQL sinks and taint steps 2022-03-09 04:20:34 +01:00
Rasmus Lerchedahl Petersen
895ce755c1 python: correct file name 2022-03-07 13:03:04 +01:00
Rasmus Lerchedahl Petersen
93750fe17f python: minimal CSRF implementation
- currectly only looks for custom django middleware
2022-03-04 12:47:23 +01:00
Rasmus Wriedt Larsen
2309f67e9b Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2022-03-01 15:50:21 +01:00
ihsinme
a9a2ca3850 Add files via upload 2022-02-25 11:09:25 +03:00
ihsinme
025701170e Add files via upload 2022-02-25 11:07:48 +03:00
Erik Krogh Kristensen
ad3399733b recognize more module exports from the factory pattern 2022-02-23 21:29:45 +01:00
Erik Krogh Kristensen
cd4685c4c5 cache RegExpCreationNode::getAReference 2022-02-21 15:04:00 +01:00
Rasmus Wriedt Larsen
3e71d7f9bb Python: Add note about / for Django upload_to
I did a test locally, something like

    import requests

    req = requests.Request(
        "POST",
        "http://127.0.0.1:8000/app/upload-test/",
        data={"name": "foo"},
        files={"upload" : ("wat/haha|!#$%^&", open("foo.txt", "rb"))},
    )

    # print(req.prepare().body.decode('ascii'))

    requests.session().send(req.prepare())

and the `wat/` part was stripped from the filename
2022-01-28 12:17:46 +01:00
Rasmus Wriedt Larsen
f962d8e72c Python: Move test to correct location 2022-01-28 11:33:21 +01:00
Rasmus Wriedt Larsen
4338c06b0d Python: Support Django FileField.upload_to 2022-01-27 17:20:16 +01:00
jorgectf
840cded9b0 Avoid using Str_ in CookieHeader 2021-11-16 19:18:00 +01:00
jorgectf
a4204cc04f Avoid using Str_ internal class 2021-11-16 19:00:04 +01:00
jorgectf
6ecb6d1a1b Adapt Django and Flask to their main modelings 2021-11-16 14:59:41 +01:00
jorgectf
e7d649f36d Make Cookie concept extend HTTP::Server::CookieWrite 2021-11-16 13:54:25 +01:00
jorgectf
83e3de1fed Polish documentation. 2021-11-05 21:05:33 +01:00
jorgectf
ed74bd6800 Merge remote-tracking branch 'origin/main' into jorgectf/python/insecure-cookie 2021-11-05 20:14:06 +01:00
jorgectf
86aac7c215 Add/Update .expected files. 2021-11-05 20:13:12 +01:00
jorgectf
a420e6e18d Add CookieInjection.qlref 2021-11-05 20:12:56 +01:00
jorgectf
cf47e8eb9c Fix endpoints' naming 2021-11-05 20:12:35 +01:00
jorgectf
b3258ce20f Add CookieInjection sample and .qhelp 2021-11-05 20:12:05 +01:00
jorgectf
d7a79469e6 Improve tests 2021-11-05 20:08:52 +01:00
jorgectf
4cb78ac654 Fix typo 2021-11-05 20:08:37 +01:00
jorgectf
cf9e9f9dd4 Add cookie injection query missing proper tests 2021-10-28 10:28:45 +02:00
jorgectf
129edd605e Update .expected 2021-10-28 09:25:56 +02:00
jorgectf
5dc1ad6f8a Polish .ql 2021-10-28 09:25:47 +02:00
jorgectf
0f2b81e0d2 Polish tests 2021-10-28 09:24:47 +02:00
jorgectf
48c3c3d8a8 Broaden scope 2021-10-27 21:00:50 +02:00
jorgectf
28ec8c9dee Merge remote-tracking branch 'origin/main' into jorgectf/python/insecure-cookie 2021-10-27 19:00:55 +02:00
Erik Krogh Kristensen
a082ed917c track flow through string replace calls that just replace single chars 2021-09-22 19:43:48 +02:00
jorgectf
54ed25a925 Change False and None scopes 2021-07-25 18:21:16 +02:00
jorgectf
c8a7f48d6e Add .expected 2021-07-25 18:18:38 +02:00
jorgectf
983465963a Polish CookieWrite 2021-07-25 18:18:29 +02:00
jorgectf
65044293dd Add CookieWrite concept 2021-07-25 17:53:58 +02:00
jorgectf
66fdd530e3 Merge branch 'jorgectf/python/headerInjection' into jorgectf/python/insecure-cookie 2021-07-25 04:35:51 +02:00
jorgectf
4f68a1777c Write documentation and example 2021-07-25 04:07:05 +02:00
jorgectf
c8983be947 Add query 2021-07-25 04:06:44 +02:00
jorgectf
8a3e4f14d1 Add tests and .qlref 2021-07-25 04:06:02 +02:00
jorgectf
0aaa9c13bd Merge remote-tracking branch 'origin/jorgectf/python/headerInjection' into jorgectf/python/insecure-cookie 2021-07-25 03:22:16 +02:00
1521 changed files with 100680 additions and 20688 deletions

View File

@@ -1,4 +1,3 @@
# -fno-rtti is required by LLVM/Swift
build --repo_env=CC=clang --repo_env=CXX=clang++ --copt="-std=c++17" --copt="-fno-rtti"
build --repo_env=CC=clang --repo_env=CXX=clang++ --copt="-std=c++17"
try-import %workspace%/local.bazelrc

2
.github/labeler.yml vendored
View File

@@ -11,7 +11,7 @@ Java:
- change-notes/**/*java.*
JS:
- javascript/**/*
- any: [ 'javascript/**/*', '!javascript/ql/experimental/adaptivethreatmodeling/**/*' ]
- change-notes/**/*javascript*
Python:

View File

@@ -30,7 +30,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.101
dotnet-version: 6.0.202
- name: Checkout repository
uses: actions/checkout@v3

View File

@@ -14,7 +14,7 @@ on:
- ".github/workflows/csv-coverage-metrics.yml"
jobs:
publish:
publish-java:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
@@ -31,13 +31,40 @@ jobs:
- name: Capture coverage information
run: |
DATABASE="${{ runner.temp }}/java-database"
codeql database analyze --format=sarif-latest --output=metrics.sarif -- "$DATABASE" ./java/ql/src/Metrics/Summaries/FrameworkCoverage.ql
codeql database analyze --format=sarif-latest --output=metrics-java.sarif -- "$DATABASE" ./java/ql/src/Metrics/Summaries/FrameworkCoverage.ql
- uses: actions/upload-artifact@v3
with:
name: metrics.sarif
path: metrics.sarif
name: metrics-java.sarif
path: metrics-java.sarif
retention-days: 20
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
uses: github/codeql-action/upload-sarif@main
with:
sarif_file: metrics.sarif
sarif_file: metrics-java.sarif
publish-csharp:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup CodeQL
uses: ./.github/actions/fetch-codeql
- name: Create empty database
run: |
DATABASE="${{ runner.temp }}/csharp-database"
PROJECT="${{ runner.temp }}/csharp-project"
dotnet new classlib --language=C# --output="$PROJECT"
codeql database create "$DATABASE" --language=csharp --source-root="$PROJECT" --command 'dotnet build /t:rebuild csharp-project.csproj /p:UseSharedCompilation=false'
- name: Capture coverage information
run: |
DATABASE="${{ runner.temp }}/csharp-database"
codeql database analyze --format=sarif-latest --output=metrics-csharp.sarif -- "$DATABASE" ./csharp/ql/src/Metrics/Summaries/FrameworkCoverage.ql
- uses: actions/upload-artifact@v3
with:
name: metrics-csharp.sarif
path: metrics-csharp.sarif
retention-days: 20
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@main
with:
sarif_file: metrics-csharp.sarif

View File

@@ -30,20 +30,15 @@ jobs:
with:
python-version: 3.8
- name: Download CodeQL CLI
uses: dsaltares/fetch-gh-release-asset@aa37ae5c44d3c9820bc12fe675e8670ecd93bd1c
with:
repo: "github/codeql-cli-binaries"
version: "latest"
file: "codeql-linux64.zip"
token: ${{ secrets.GITHUB_TOKEN }}
# Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo
uses: ./codeql/.github/actions/fetch-codeql
- name: Unzip CodeQL CLI
run: unzip -d codeql-cli codeql-linux64.zip
- name: Build code scanning query list
run: |
PATH="$PATH:codeql-cli/codeql" python codeql/misc/scripts/generate-code-scanning-query-list.py > code-scanning-query-list.csv
python codeql/misc/scripts/generate-code-scanning-query-list.py > code-scanning-query-list.csv
- name: Upload code scanning query list
uses: actions/upload-artifact@v3
with:
name: code-scanning-query-list
path: code-scanning-query-list.csv

View File

@@ -13,18 +13,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
with:
python-version: '~3.8'
cache: 'pip'
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- name: Install dependencies
run: |
pip install -r swift/codegen/requirements.txt
- name: Run unit tests
run: |
bazel test //swift/codegen:tests --test_output=errors
bazel test //swift/codegen/test --test_output=errors
- name: Check that code was generated
run: |
bazel run //swift/codegen

3
.gitignore vendored
View File

@@ -37,5 +37,8 @@ csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
# links created by bazel
/bazel-*
# local bazel options
/local.bazelrc
# CLion project files
/.clwb

View File

@@ -47,5 +47,5 @@ repos:
name: Run Swift code generation unit tests
files: ^swift/codegen/.*\.py$
language: system
entry: bazel test //swift/codegen:tests
entry: bazel test //swift/codegen/test
pass_filenames: false

View File

@@ -4,6 +4,9 @@
/javascript/ @github/codeql-javascript
/python/ @github/codeql-python
/ruby/ @github/codeql-ruby
/swift/ @github/codeql-c
/java/kotlin-extractor/ @github/codeql-kotlin
/java/kotlin-explorer/ @github/codeql-kotlin
# ML-powered queries
/javascript/ql/experimental/adaptivethreatmodeling/ @github/codeql-ml-powered-queries-reviewers

View File

@@ -1,3 +1,5 @@
## 0.2.1
## 0.2.0
### Breaking Changes

View File

@@ -0,0 +1 @@
## 0.2.1

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.2.0
lastReleaseVersion: 0.2.1

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.2.0
version: 0.2.1
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -38,8 +38,8 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* int z = min(5, 7);
* ```
* The full signature of the function called on the last line would be
* "min<int>(int, int) -> int", and the full signature of the uninstantiated
* template on the first line would be "min<T>(T, T) -> T".
* `min<int>(int, int) -> int`, and the full signature of the uninstantiated
* template on the first line would be `min<T>(T, T) -> T`.
*/
string getFullSignature() {
exists(string name, string templateArgs, string args |

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -328,6 +328,9 @@ private module Cached {
cached
predicate clearsContentCached(Node n, ContentSet c) { clearsContent(n, c) }
cached
predicate expectsContentCached(Node n, ContentSet c) { expectsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -198,6 +198,12 @@ predicate clearsContent(Node n, Content c) {
none() // stub implementation
}
/**
* Holds if the value that is being tracked is expected to be stored inside content `c`
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) { none() }
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -328,6 +328,9 @@ private module Cached {
cached
predicate clearsContentCached(Node n, ContentSet c) { clearsContent(n, c) }
cached
predicate expectsContentCached(Node n, ContentSet c) { expectsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }

View File

@@ -279,6 +279,12 @@ predicate clearsContent(Node n, Content c) {
none() // stub implementation
}
/**
* Holds if the value that is being tracked is expected to be stored inside content `c`
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) { none() }
/** Gets the type of `n` used for type pruning. */
IRType getNodeType(Node n) {
suppressUnusedNode(n) and

View File

@@ -5,8 +5,6 @@
import cpp
import semmle.code.cpp.controlflow.Dominance
// `GlobalValueNumbering` is only imported to prevent IR re-evaluation.
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
import semmle.code.cpp.controlflow.Guards

View File

@@ -1,3 +1,9 @@
## 0.1.2
### Minor Analysis Improvements
* The "XML external entity expansion" (`cpp/external-entity-expansion`) query has been extended to support a broader selection of XML libraries and interfaces.
## 0.1.1
### New Queries

View File

@@ -14,9 +14,6 @@
*/
import cpp
// We don't actually use the global value numbering library in this query, but without it we end up
// recomputing the IR.
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.MustFlow
import PathGraph

View File

@@ -2,7 +2,7 @@
* @name Suspicious call to memset
* @description Use of memset where the size argument is computed as the size of
* some non-struct type. When initializing a buffer, you should specify
* its size as <number of elements> * <size of one element> to ensure
* its size as `<number of elements> * <size of one element>` to ensure
* portability.
* @kind problem
* @id cpp/suspicious-call-to-memset

View File

@@ -15,9 +15,6 @@
*/
import cpp
// We don't actually use the global value numbering library in this query, but without it we end up
// recomputing the IR.
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.MustFlow
import PathGraph

View File

@@ -16,6 +16,7 @@ import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
import DataFlow::PathGraph
import semmle.code.cpp.ir.IR
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* A flow state representing a possible configuration of an XML object.
@@ -57,42 +58,58 @@ class XercesDOMParserClass extends Class {
}
/**
* Gets a valid flow state for `XercesDOMParser` flow.
* The `SAXParser` class.
*/
class SaxParserClass extends Class {
SaxParserClass() { this.hasName("SAXParser") }
}
/**
* The `SAX2XMLReader` class.
*/
class Sax2XmlReader extends Class {
Sax2XmlReader() { this.hasName("SAX2XMLReader") }
}
/**
* Gets a valid flow state for `AbstractDOMParser` or `SAXParser` flow.
*
* These flow states take the form `XercesDOM-A-B`, where:
* These flow states take the form `Xerces-A-B`, where:
* - A is 1 if `setDisableDefaultEntityResolution` is `true`, 0 otherwise.
* - B is 1 if `setCreateEntityReferenceNodes` is `true`, 0 otherwise.
*/
predicate encodeXercesDOMFlowState(
predicate encodeXercesFlowState(
string flowstate, int disabledDefaultEntityResolution, int createEntityReferenceNodes
) {
flowstate = "XercesDOM-0-0" and
flowstate = "Xerces-0-0" and
disabledDefaultEntityResolution = 0 and
createEntityReferenceNodes = 0
or
flowstate = "XercesDOM-0-1" and
flowstate = "Xerces-0-1" and
disabledDefaultEntityResolution = 0 and
createEntityReferenceNodes = 1
or
flowstate = "XercesDOM-1-0" and
flowstate = "Xerces-1-0" and
disabledDefaultEntityResolution = 1 and
createEntityReferenceNodes = 0
or
flowstate = "XercesDOM-1-1" and
flowstate = "Xerces-1-1" and
disabledDefaultEntityResolution = 1 and
createEntityReferenceNodes = 1
}
/**
* A flow state representing the configuration of a `XercesDOMParser` object.
* A flow state representing the configuration of an `AbstractDOMParser` or
* `SAXParser` object.
*/
class XercesDOMParserFlowState extends XXEFlowState {
XercesDOMParserFlowState() { encodeXercesDOMFlowState(this, _, _) }
class XercesFlowState extends XXEFlowState {
XercesFlowState() { encodeXercesFlowState(this, _, _) }
}
/**
* A flow state transformer for a call to
* `AbstractDOMParser.setDisableDefaultEntityResolution`. Transforms the flow
* `AbstractDOMParser.setDisableDefaultEntityResolution` or
* `SAXParser.setDisableDefaultEntityResolution`. Transforms the flow
* state through the qualifier according to the setting in the parameter.
*/
class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
@@ -101,7 +118,10 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
DisableDefaultEntityResolutionTranformer() {
exists(Call call, Function f |
call.getTarget() = f and
f.getDeclaringType() instanceof AbstractDOMParserClass and
(
f.getDeclaringType() instanceof AbstractDOMParserClass or
f.getDeclaringType() instanceof SaxParserClass
) and
f.hasName("setDisableDefaultEntityResolution") and
this = call.getQualifier() and
newValue = call.getArgument(0)
@@ -110,13 +130,13 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
final override XXEFlowState transform(XXEFlowState flowstate) {
exists(int createEntityReferenceNodes |
encodeXercesDOMFlowState(flowstate, _, createEntityReferenceNodes) and
encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and
(
newValue.getValue().toInt() = 1 and // true
encodeXercesDOMFlowState(result, 1, createEntityReferenceNodes)
globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // true
encodeXercesFlowState(result, 1, createEntityReferenceNodes)
or
not newValue.getValue().toInt() = 1 and // false or unknown
encodeXercesDOMFlowState(result, 0, createEntityReferenceNodes)
not globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // false or unknown
encodeXercesFlowState(result, 0, createEntityReferenceNodes)
)
)
}
@@ -133,8 +153,7 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
CreateEntityReferenceNodesTranformer() {
exists(Call call, Function f |
call.getTarget() = f and
f.getDeclaringType() instanceof AbstractDOMParserClass and
f.hasName("setCreateEntityReferenceNodes") and
f.getClassAndName("setCreateEntityReferenceNodes") instanceof AbstractDOMParserClass and
this = call.getQualifier() and
newValue = call.getArgument(0)
)
@@ -142,27 +161,76 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
final override XXEFlowState transform(XXEFlowState flowstate) {
exists(int disabledDefaultEntityResolution |
encodeXercesDOMFlowState(flowstate, disabledDefaultEntityResolution, _) and
encodeXercesFlowState(flowstate, disabledDefaultEntityResolution, _) and
(
newValue.getValue().toInt() = 1 and // true
encodeXercesDOMFlowState(result, disabledDefaultEntityResolution, 1)
globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // true
encodeXercesFlowState(result, disabledDefaultEntityResolution, 1)
or
not newValue.getValue().toInt() = 1 and // false or unknown
encodeXercesDOMFlowState(result, disabledDefaultEntityResolution, 0)
not globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // false or unknown
encodeXercesFlowState(result, disabledDefaultEntityResolution, 0)
)
)
}
}
/**
* The `AbstractDOMParser.parse` method.
* The `XMLUni.fgXercesDisableDefaultEntityResolution` constant.
*/
class ParseFunction extends Function {
ParseFunction() { this.getClassAndName("parse") instanceof AbstractDOMParserClass }
class FeatureDisableDefaultEntityResolution extends Variable {
FeatureDisableDefaultEntityResolution() {
this.getName() = "fgXercesDisableDefaultEntityResolution" and
this.getDeclaringType().getName() = "XMLUni"
}
}
/**
* The `createLSParser` function that returns a newly created `LSParser` object.
* A flow state transformer for a call to `SAX2XMLReader.setFeature`
* specifying the feature `XMLUni::fgXercesDisableDefaultEntityResolution`.
* Transforms the flow state through the qualifier according to this setting.
*/
class SetFeatureTranformer extends XXEFlowStateTranformer {
Expr newValue;
SetFeatureTranformer() {
exists(Call call, Function f |
call.getTarget() = f and
f.getClassAndName("setFeature") instanceof Sax2XmlReader and
this = call.getQualifier() and
globalValueNumber(call.getArgument(0)).getAnExpr().(VariableAccess).getTarget() instanceof
FeatureDisableDefaultEntityResolution and
newValue = call.getArgument(1)
)
}
final override XXEFlowState transform(XXEFlowState flowstate) {
exists(int createEntityReferenceNodes |
encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and
(
globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // true
encodeXercesFlowState(result, 1, createEntityReferenceNodes)
or
not globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // false or unknown
encodeXercesFlowState(result, 0, createEntityReferenceNodes)
)
)
}
}
/**
* The `AbstractDOMParser.parse`, `SAXParser.parse` or `SAX2XMLReader.parse`
* method.
*/
class ParseFunction extends Function {
ParseFunction() {
this.getClassAndName("parse") instanceof AbstractDOMParserClass or
this.getClassAndName("parse") instanceof SaxParserClass or
this.getClassAndName("parse") instanceof Sax2XmlReader
}
}
/**
* The `createLSParser` function that returns a newly created `DOMLSParser`
* object.
*/
class CreateLSParser extends Function {
CreateLSParser() {
@@ -171,6 +239,53 @@ class CreateLSParser extends Function {
}
}
/**
* The `createXMLReader` function that returns a newly created `SAX2XMLReader`
* object.
*/
class CreateXmlReader extends Function {
CreateXmlReader() {
this.hasName("createXMLReader") and
this.getUnspecifiedType().(PointerType).getBaseType() instanceof Sax2XmlReader // returns a `SAX2XMLReader *`.
}
}
/**
* A call to a `libxml2` function that parses XML.
*/
class Libxml2ParseCall extends FunctionCall {
int optionsArg;
Libxml2ParseCall() {
exists(string fname | this.getTarget().getName() = fname |
fname = "xmlCtxtUseOptions" and optionsArg = 1
or
fname = "xmlReadFile" and optionsArg = 2
or
fname = ["xmlCtxtReadFile", "xmlParseInNodeContext", "xmlReadDoc", "xmlReadFd"] and
optionsArg = 3
or
fname = ["xmlCtxtReadDoc", "xmlCtxtReadFd", "xmlReadMemory"] and optionsArg = 4
or
fname = ["xmlCtxtReadMemory", "xmlReadIO"] and optionsArg = 5
or
fname = "xmlCtxtReadIO" and optionsArg = 6
)
}
/**
* Gets the argument that specifies `xmlParserOption`s.
*/
Expr getOptions() { result = this.getArgument(optionsArg) }
}
/**
* An `xmlParserOption` for `libxml2` that is considered unsafe.
*/
class Libxml2BadOption extends EnumConstant {
Libxml2BadOption() { this.getName() = ["XML_PARSE_NOENT", "XML_PARSE_DTDLOAD"] }
}
/**
* A configuration for tracking XML objects and their states.
*/
@@ -184,14 +299,47 @@ class XXEConfiguration extends DataFlow::Configuration {
call.getStaticCallTarget() = any(XercesDOMParserClass c).getAConstructor() and
node.asInstruction().(WriteSideEffectInstruction).getDestinationAddress() =
call.getThisArgument() and
encodeXercesDOMFlowState(flowstate, 0, 1) // default configuration
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
or
// source is the result of a call to `createLSParser`.
exists(Call call |
call.getTarget() instanceof CreateLSParser and
call = node.asExpr() and
encodeXercesDOMFlowState(flowstate, 0, 1) // default configuration
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
or
// source is the write on `this` of a call to the `SAXParser`
// constructor.
exists(CallInstruction call |
call.getStaticCallTarget() = any(SaxParserClass c).getAConstructor() and
node.asInstruction().(WriteSideEffectInstruction).getDestinationAddress() =
call.getThisArgument() and
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
or
// source is the result of a call to `createXMLReader`.
exists(Call call |
call.getTarget() instanceof CreateXmlReader and
call = node.asExpr() and
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
or
// source is an `options` argument on a `libxml2` parse call that specifies
// at least one unsafe option.
//
// note: we don't need to track an XML object for `libxml2`, so we don't
// really need data flow. Nevertheless we jam it into this configuration,
// with matching sources and sinks. This allows results to be presented by
// the same query, in a consistent way as other results with flow paths.
exists(Libxml2ParseCall call, Expr options |
options = call.getOptions() and
node.asExpr() = options and
flowstate = "libxml2" and
exists(Libxml2BadOption opt |
globalValueNumber(options).getAnExpr().getValue().toInt().bitAnd(opt.getValue().toInt()) !=
0
)
)
}
@@ -201,8 +349,15 @@ class XXEConfiguration extends DataFlow::Configuration {
call.getTarget() instanceof ParseFunction and
call.getQualifier() = node.asConvertedExpr()
) and
flowstate instanceof XercesDOMParserFlowState and
not encodeXercesDOMFlowState(flowstate, 1, 1) // safe configuration
flowstate instanceof XercesFlowState and
not encodeXercesFlowState(flowstate, 1, 1) // safe configuration
or
// sink is the `options` argument on a `libxml2` parse call.
exists(Libxml2ParseCall call, Expr options |
options = call.getOptions() and
node.asExpr() = options and
flowstate = "libxml2"
)
}
override predicate isAdditionalFlowStep(

View File

@@ -0,0 +1,5 @@
## 0.1.2
### Minor Analysis Improvements
* The "XML external entity expansion" (`cpp/external-entity-expansion`) query has been extended to support a broader selection of XML libraries and interfaces.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.1.1
lastReleaseVersion: 0.1.2

View File

@@ -0,0 +1,49 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Using only a call to
<code>pam_authenticate</code>
to check the validity of a login can lead to authorization bypass vulnerabilities.
</p>
<p>
A
<code>pam_authenticate</code>
only verifies the credentials of a user. It does not check if a user has an appropriate authorization to actually login. This means a user with a expired login or a password can still access the system.
</p>
</overview>
<recommendation>
<p>
A call to
<code>pam_authenticate</code>
should be followed by a call to
<code>pam_acct_mgmt</code>
to check if a user is allowed to login.
</p>
</recommendation>
<example>
<p>
In the following example, the code only checks the credentials of a user. Hence, in this case, a user expired with expired creds can still login. This can be verified by creating a new user account, expiring it with
<code>chage -E0 `username` </code>
and then trying to log in.
</p>
<sample src="PamAuthorizationBad.cpp" />
<p>
This can be avoided by calling
<code>pam_acct_mgmt</code>
call to verify access as has been done in the snippet shown below.
</p>
<sample src="PamAuthorizationGood.cpp" />
</example>
<references>
<li>
Man-Page:
<a href="https://man7.org/linux/man-pages/man3/pam_acct_mgmt.3.html">pam_acct_mgmt</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,34 @@
/**
* @name PAM Authorization bypass
* @description Only using `pam_authenticate` call to authenticate users can lead to authorization vulnerabilities.
* @kind problem
* @problem.severity error
* @id cpp/pam-auth-bypass
* @tags security
* external/cwe/cwe-285
*/
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
private class PamAuthCall extends FunctionCall {
PamAuthCall() {
exists(Function f | f.hasName("pam_authenticate") | f.getACallToThisFunction() = this)
}
}
private class PamActMgmtCall extends FunctionCall {
PamActMgmtCall() {
exists(Function f | f.hasName("pam_acct_mgmt") | f.getACallToThisFunction() = this)
}
}
from PamAuthCall pa, Expr handle
where
pa.getArgument(0) = handle and
not exists(PamActMgmtCall pac |
globalValueNumber(handle) = globalValueNumber(pac.getArgument(0)) or
DataFlow::localExprFlow(handle, pac.getArgument(0))
)
select pa, "This PAM authentication call may be lead to an authorization bypass."

View File

@@ -0,0 +1,20 @@
bool PamAuthGood(const std::string &username_in,
const std::string &password_in,
std::string &authenticated_username)
{
struct pam_handle *pamh = nullptr; /* pam session handle */
const char *username = username_in.c_str();
int err = pam_start("test", username,
0, &pamh);
if (err != PAM_SUCCESS)
{
return false;
}
err = pam_authenticate(pamh, 0); // BAD
if (err != PAM_SUCCESS)
return err;
return true;
}

View File

@@ -0,0 +1,24 @@
bool PamAuthGood(const std::string &username_in,
const std::string &password_in,
std::string &authenticated_username)
{
struct pam_handle *pamh = nullptr; /* pam session handle */
const char *username = username_in.c_str();
int err = pam_start("test", username,
0, &pamh);
if (err != PAM_SUCCESS)
{
return false;
}
err = pam_authenticate(pamh, 0);
if (err != PAM_SUCCESS)
return err;
err = pam_acct_mgmt(pamh, 0); // GOOD
if (err != PAM_SUCCESS)
return err;
return true;
}

View File

@@ -0,0 +1,48 @@
...
try {
if (checkValue) throw exception();
bufMyData = new myData*[sizeInt];
}
catch (...)
{
for (size_t i = 0; i < sizeInt; i++)
{
delete[] bufMyData[i]->buffer; // BAD
delete bufMyData[i];
}
...
try {
if (checkValue) throw exception();
bufMyData = new myData*[sizeInt];
}
catch (...)
{
for (size_t i = 0; i < sizeInt; i++)
{
if(bufMyData[i])
{
delete[] bufMyData[i]->buffer; // GOOD
delete bufMyData[i];
}
}
...
catch (const exception &) {
delete valData;
throw;
}
catch (...)
{
delete valData; // BAD
...
catch (const exception &) {
delete valData;
valData = NULL;
throw;
}
catch (...)
{
delete valData; // GOOD
...

View File

@@ -0,0 +1,23 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>When releasing memory in a catch block, be sure that the memory was allocated and has not already been released.</p>
</overview>
<example>
<p>The following example shows erroneous and fixed ways to use exception handling.</p>
<sample src="DangerousUseOfExceptionBlocks.cpp" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers">EXP34-C. Do not dereference null pointers</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,199 @@
/**
* @name Dangerous use of exception blocks.
* @description When clearing the data in the catch block, you must be sure that the memory was allocated before the exception.
* @kind problem
* @id cpp/dangerous-use-of-exception-blocks
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-476
* external/cwe/cwe-415
*/
import cpp
/** Holds if `vr` may be released in the `try` block associated with `cb`, or in a `catch` block prior to `cb`. */
pragma[inline]
predicate doubleCallDelete(BlockStmt b, CatchAnyBlock cb, Variable vr) {
// Search for exceptions after freeing memory.
exists(Expr e1 |
// `e1` is a delete of `vr`
(
e1 = vr.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr().(DeleteArrayExpr) or
e1 = vr.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr().(DeleteExpr)
) and
e1.getEnclosingFunction() = cb.getEnclosingFunction() and
// there is no assignment `vr = 0` in the `try` block after `e1`
not exists(AssignExpr ae |
ae.getLValue().(VariableAccess).getTarget() = vr and
ae.getRValue().getValue() = "0" and
e1.getASuccessor+() = ae and
ae.getEnclosingStmt().getParentStmt*() = b
) and
// `e2` is a `throw` (or a function call that may throw) that occurs in the `try` or `catch` block after `e1`
exists(Expr e2, ThrowExpr th |
(
e2 = th or
e2 = th.getEnclosingFunction().getACallToThisFunction()
) and
e2.getEnclosingStmt().getParentStmt*() = b and
e1.getASuccessor+() = e2
) and
e1.getEnclosingStmt().getParentStmt*() = b and
(
// Search for a situation where there is a release in the block of `try`.
b = cb.getTryStmt().getStmt()
or
// Search for a situation when there is a higher catch block that also frees memory.
exists(b.(CatchBlock).getParameter())
) and
// Exclude the presence of a check in catch block.
not exists(IfStmt ifst | ifst.getEnclosingStmt().getParentStmt*() = cb.getAStmt())
)
}
/** Holds if an exception can be thrown before the memory is allocated, and when the exception is handled, an attempt is made to access unallocated memory in the catch block. */
pragma[inline]
predicate pointerDereference(CatchAnyBlock cb, Variable vr, Variable vro) {
// Search exceptions before allocating memory.
exists(Expr e0, Expr e1 |
(
// `e0` is a `new` expression (or equivalent function call) assigned to `vro`
exists(AssignExpr ase |
ase = vro.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr() and
(
e0 = ase.getRValue().(NewOrNewArrayExpr) or
e0 = ase.getRValue().(NewOrNewArrayExpr).getEnclosingFunction().getACallToThisFunction()
) and
vro = ase.getLValue().(VariableAccess).getTarget()
)
or
// `e0` is a `new` expression (or equivalent function call) assigned to the array element `vro`
exists(AssignExpr ase |
ase = vro.getAnAccess().(Qualifier).getEnclosingStmt().(ExprStmt).getExpr() and
(
e0 = ase.getRValue().(NewOrNewArrayExpr) or
e0 = ase.getRValue().(NewOrNewArrayExpr).getEnclosingFunction().getACallToThisFunction()
) and
not ase.getLValue() instanceof VariableAccess and
vro = ase.getLValue().getAPredecessor().(VariableAccess).getTarget()
)
) and
// `e1` is a `new` expression (or equivalent function call) assigned to `vr`
exists(AssignExpr ase |
ase = vr.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr() and
(
e1 = ase.getRValue().(NewOrNewArrayExpr) or
e1 = ase.getRValue().(NewOrNewArrayExpr).getEnclosingFunction().getACallToThisFunction()
) and
vr = ase.getLValue().(VariableAccess).getTarget()
) and
e0.getASuccessor*() = e1 and
e0.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
e1.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
// `e2` is a `throw` (or a function call that may throw) that occurs in the `try` block before `e0`
exists(Expr e2, ThrowExpr th |
(
e2 = th or
e2 = th.getEnclosingFunction().getACallToThisFunction()
) and
e2.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
e2.getASuccessor+() = e0
)
) and
// We exclude checking the value of a variable or its parent in the catch block.
not exists(IfStmt ifst |
ifst.getEnclosingStmt().getParentStmt*() = cb.getAStmt() and
(
ifst.getCondition().getAChild*().(VariableAccess).getTarget() = vr or
ifst.getCondition().getAChild*().(VariableAccess).getTarget() = vro
)
)
}
/** Holds if `vro` may be released in the `catch`. */
pragma[inline]
predicate newThrowDelete(CatchAnyBlock cb, Variable vro) {
exists(Expr e0, AssignExpr ase, NewOrNewArrayExpr nae |
ase = vro.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr() and
nae = ase.getRValue() and
not nae.getAChild*().toString() = "nothrow" and
(
e0 = nae or
e0 = nae.getEnclosingFunction().getACallToThisFunction()
) and
vro = ase.getLValue().(VariableAccess).getTarget() and
e0.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
not exists(AssignExpr ase1 |
vro = ase1.getLValue().(VariableAccess).getTarget() and
ase1.getRValue().getValue() = "0" and
ase1.getASuccessor*() = e0
)
) and
not exists(Initializer it |
vro.getInitializer() = it and
it.getExpr().getValue() = "0"
) and
not exists(ConstructorFieldInit ci | vro = ci.getTarget())
}
from CatchAnyBlock cb, string msg
where
exists(Variable vr, Variable vro, Expr exp |
exp.getEnclosingStmt().getParentStmt*() = cb and
exists(VariableAccess va |
(
(
va = exp.(DeleteArrayExpr).getExpr().getAPredecessor+().(Qualifier) or
va = exp.(DeleteArrayExpr).getExpr().getAPredecessor+()
) and
vr = exp.(DeleteArrayExpr).getExpr().(VariableAccess).getTarget()
or
(
va = exp.(DeleteExpr).getExpr().getAPredecessor+().(Qualifier) or
va = exp.(DeleteExpr).getExpr().getAPredecessor+()
) and
vr = exp.(DeleteExpr).getExpr().(VariableAccess).getTarget()
) and
va.getEnclosingStmt() = exp.getEnclosingStmt() and
vro = va.getTarget() and
vr != vro
) and
pointerDereference(cb, vr, vro) and
msg =
"it is possible to dereference a pointer when accessing a " + vr.getName() +
", since it is possible to throw an exception before the memory for the " + vro.getName() +
" is allocated"
)
or
exists(Expr exp, Variable vr |
(
exp.(DeleteExpr).getEnclosingStmt().getParentStmt*() = cb and
vr = exp.(DeleteExpr).getExpr().(VariableAccess).getTarget()
or
exp.(DeleteArrayExpr).getEnclosingStmt().getParentStmt*() = cb and
vr = exp.(DeleteArrayExpr).getExpr().(VariableAccess).getTarget()
) and
doubleCallDelete(_, cb, vr) and
msg =
"This allocation may have been released in the try block or a previous catch block." +
vr.getName()
)
or
exists(Variable vro, Expr exp |
exp.getEnclosingStmt().getParentStmt*() = cb and
exists(VariableAccess va |
(
va = exp.(DeleteArrayExpr).getExpr() or
va = exp.(DeleteExpr).getExpr()
) and
va.getEnclosingStmt() = exp.getEnclosingStmt() and
vro = va.getTarget()
) and
newThrowDelete(cb, vro) and
msg =
"If the allocation in the try block fails, then an unallocated pointer " + vro.getName() +
" will be freed in the catch block."
)
select cb, msg

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.1.1
version: 0.1.2
groups:
- cpp
- queries

View File

@@ -0,0 +1 @@
| test.cpp:14:16:14:16 | p | unsafe_put_user write user-mode pointer $@ without check. | test.cpp:14:16:14:16 | p | p |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql

View File

@@ -0,0 +1,82 @@
typedef unsigned long size_t;
void SYSC_SOMESYSTEMCALL(void *param);
bool user_access_begin_impl(const void *where, size_t sz);
void user_access_end_impl();
#define user_access_begin(where, sz) user_access_begin_impl(where, sz)
#define user_access_end() user_access_end_impl()
void unsafe_put_user_impl(int what, const void *where, size_t sz);
#define unsafe_put_user(what, where) unsafe_put_user_impl( (what), (where), sizeof(*(where)) )
void test1(int p)
{
SYSC_SOMESYSTEMCALL(&p);
unsafe_put_user(123, &p); // BAD
}
void test2(int p)
{
SYSC_SOMESYSTEMCALL(&p);
if (user_access_begin(&p, sizeof(p)))
{
unsafe_put_user(123, &p); // GOOD
user_access_end();
}
}
void test3()
{
int v;
SYSC_SOMESYSTEMCALL(&v);
unsafe_put_user(123, &v); // BAD [NOT DETECTED]
}
void test4()
{
int v;
SYSC_SOMESYSTEMCALL(&v);
if (user_access_begin(&v, sizeof(v)))
{
unsafe_put_user(123, &v); // GOOD
user_access_end();
}
}
struct data
{
int x;
};
void test5()
{
data myData;
SYSC_SOMESYSTEMCALL(&myData);
unsafe_put_user(123, &(myData.x)); // BAD [NOT DETECTED]
}
void test6()
{
data myData;
SYSC_SOMESYSTEMCALL(&myData);
if (user_access_begin(&myData, sizeof(myData)))
{
unsafe_put_user(123, &(myData.x)); // GOOD
user_access_end();
}
}

View File

@@ -0,0 +1 @@
| test.cpp:29:11:29:26 | call to pam_authenticate | This PAM authentication call may be lead to an authorization bypass. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-285/PamAuthorization.ql

View File

@@ -0,0 +1,59 @@
#include "../../../../../library-tests/dataflow/taint-tests/stl.h"
using namespace std;
#define PAM_SUCCESS 1
typedef struct pam_handle
{
};
int pam_start(std::string servicename, std::string username, int a, struct pam_handle **);
int pam_authenticate(struct pam_handle *, int e);
int pam_acct_mgmt(struct pam_handle *, int e);
bool PamAuthBad(const std::string &username_in,
const std::string &password_in,
std::string &authenticated_username)
{
struct pam_handle *pamh = nullptr; /* pam session handle */
const char *username = username_in.c_str();
int err = pam_start("test", username,
0, &pamh);
if (err != PAM_SUCCESS)
{
return false;
}
err = pam_authenticate(pamh, 0);
if (err != PAM_SUCCESS)
return err;
return true;
}
bool PamAuthGood(const std::string &username_in,
const std::string &password_in,
std::string &authenticated_username)
{
struct pam_handle *pamh = nullptr; /* pam session handle */
const char *username = username_in.c_str();
int err = pam_start("test", username,
0, &pamh);
if (err != PAM_SUCCESS)
{
return false;
}
err = pam_authenticate(pamh, 0);
if (err != PAM_SUCCESS)
return err;
err = pam_acct_mgmt(pamh, 0);
if (err != PAM_SUCCESS)
return err;
return true;
}

View File

@@ -0,0 +1,8 @@
| test.cpp:63:3:71:3 | { ... } | If the allocation in the try block fails, then an unallocated pointer bufMyData will be freed in the catch block. |
| test.cpp:63:3:71:3 | { ... } | If the allocation in the try block fails, then an unallocated pointer buffer will be freed in the catch block. |
| test.cpp:63:3:71:3 | { ... } | it is possible to dereference a pointer when accessing a buffer, since it is possible to throw an exception before the memory for the bufMyData is allocated |
| test.cpp:91:3:100:3 | { ... } | If the allocation in the try block fails, then an unallocated pointer buffer will be freed in the catch block. |
| test.cpp:120:3:128:3 | { ... } | If the allocation in the try block fails, then an unallocated pointer buffer will be freed in the catch block. |
| test.cpp:143:3:151:3 | { ... } | If the allocation in the try block fails, then an unallocated pointer buffer will be freed in the catch block. |
| test.cpp:181:3:183:3 | { ... } | This allocation may have been released in the try block or a previous catch block.valData |
| test.cpp:219:3:221:3 | { ... } | This allocation may have been released in the try block or a previous catch block.valData |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-476/DangerousUseOfExceptionBlocks.ql

View File

@@ -0,0 +1,255 @@
#define NULL ((void*)0)
typedef unsigned long size_t;
namespace std {
enum class align_val_t : size_t {};
}
class exception {};
void cleanFunction();
void* operator new(size_t, float);
void* operator new[](size_t, float);
void* operator new(size_t, std::align_val_t, float);
void* operator new[](size_t, std::align_val_t, float);
void operator delete(void*, float);
void operator delete[](void*, float);
void operator delete(void*, std::align_val_t, float);
void operator delete[](void*, std::align_val_t, float);
struct myData
{
int sizeInt;
char* buffer;
};
struct myGlobalData
{
int sizeInt;
myData** bufMyData;
};
void allocData(myData ** bufMyData) {
for (size_t i = 0; i < 10; i++)
{
bufMyData[i] = new myData;
bufMyData[i]->sizeInt = 10;
bufMyData[i]->buffer = new char[10];
}
}
void throwFunction(int a) {
if (a == 5) throw "my exception!";
}
void throwFunction2(int a) {
if (a == 5) throw exception();
}
void funcWork1b() {
int a;
myData **bufMyData;
try {
cleanFunction();
throwFunction(a);
bufMyData = new myData*[10];
cleanFunction();
allocData(bufMyData);
cleanFunction();
}
catch (...)
{
for (size_t i = 0; i < 10; i++)
{
delete[] bufMyData[i]->buffer; // BAD
delete bufMyData[i];
}
delete [] bufMyData;
}
}
void funcWork1() {
int a;
int i;
myData **bufMyData;
bufMyData = new myData*[10];
for (i = 0; i < 10; i++)
bufMyData[i] = 0;
try {
cleanFunction();
throwFunction(a);
cleanFunction();
allocData(bufMyData);
cleanFunction();
}
catch (...)
{
for (size_t i = 0; i < 10; i++)
{
if (bufMyData[i])
delete[] bufMyData[i]->buffer; // BAD
delete bufMyData[i];
}
delete [] bufMyData;
}
}
void funcWork2() {
int a;
myData **bufMyData;
bufMyData = new myData*[10];
try {
do {
cleanFunction();
allocData(bufMyData);
cleanFunction();
throwFunction(a);
}
while(0);
}
catch (...)
{
for (size_t i = 0; i < 10; i++)
{
delete[] bufMyData[i]->buffer; // BAD
delete bufMyData[i];
}
delete [] bufMyData;
}
}
void funcWork3() {
int a;
myData **bufMyData;
bufMyData = new myData*[10];
try {
cleanFunction();
allocData(bufMyData);
cleanFunction();
throwFunction(a);
}
catch (...)
{
for (size_t i = 0; i < 10; i++)
{
delete[] bufMyData[i]->buffer; // BAD
delete bufMyData[i];
}
delete [] bufMyData;
}
}
void funcWork4() {
int a;
myGlobalData *valData = 0;
try {
valData = new myGlobalData;
cleanFunction();
delete valData;
valData = 0;
throwFunction(a);
}
catch (...)
{
delete valData; // GOOD
}
}
void funcWork4b() {
int a;
myGlobalData *valData = 0;
try {
valData = new myGlobalData;
cleanFunction();
delete valData;
throwFunction(a);
}
catch (...)
{
delete valData; // BAD
}
}
void funcWork5() {
int a;
myGlobalData *valData = 0;
try {
valData = new myGlobalData;
cleanFunction();
delete valData;
valData = 0;
throwFunction2(a);
}
catch (const exception &) {
delete valData;
valData = 0;
throw;
}
catch (...)
{
delete valData; // GOOD
}
}
void funcWork5b() {
int a;
myGlobalData *valData = 0;
try {
valData = new myGlobalData;
cleanFunction();
throwFunction2(a);
}
catch (const exception &) {
delete valData;
throw;
}
catch (...)
{
delete valData; // BAD
}
}
void funcWork6() {
int a;
int flagB = 0;
myGlobalData *valData = 0;
try {
valData = new myGlobalData;
cleanFunction();
throwFunction2(a);
}
catch (const exception &) {
delete valData;
flagB = 1;
throw;
}
catch (...)
{
if(flagB == 0)
delete valData; // GOOD
}
}
void runnerFunc()
{
funcWork1();
funcWork1b();
funcWork2();
funcWork3();
funcWork4();
funcWork4b();
funcWork5();
funcWork5b();
funcWork6();
}

View File

@@ -1,80 +1,106 @@
edges
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p |
| tests.cpp:53:19:53:19 | VariableAddress [post update] | tests.cpp:55:2:55:2 | p |
| tests.cpp:53:23:53:43 | XercesDOMParser output argument | tests.cpp:53:19:53:19 | VariableAddress [post update] |
| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p |
| tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p |
| tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p |
| tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p |
| tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p |
| tests.cpp:28:23:28:43 | XercesDOMParser output argument | tests.cpp:31:2:31:2 | p |
| tests.cpp:35:19:35:19 | VariableAddress [post update] | tests.cpp:37:2:37:2 | p |
| tests.cpp:35:23:35:43 | XercesDOMParser output argument | tests.cpp:35:19:35:19 | VariableAddress [post update] |
| tests.cpp:37:2:37:2 | p | tests.cpp:38:2:38:2 | p |
| tests.cpp:38:2:38:2 | p | tests.cpp:39:2:39:2 | p |
| tests.cpp:51:19:51:19 | VariableAddress [post update] | tests.cpp:53:2:53:2 | p |
| tests.cpp:51:23:51:43 | XercesDOMParser output argument | tests.cpp:51:19:51:19 | VariableAddress [post update] |
| tests.cpp:53:2:53:2 | p | tests.cpp:54:2:54:2 | p |
| tests.cpp:54:2:54:2 | p | tests.cpp:55:2:55:2 | p |
| tests.cpp:55:2:55:2 | p | tests.cpp:56:2:56:2 | p |
| tests.cpp:55:2:55:2 | p | tests.cpp:56:2:56:2 | p |
| tests.cpp:56:2:56:2 | p | tests.cpp:57:2:57:2 | p |
| tests.cpp:69:19:69:19 | VariableAddress [post update] | tests.cpp:71:2:71:2 | p |
| tests.cpp:69:23:69:43 | XercesDOMParser output argument | tests.cpp:69:19:69:19 | VariableAddress [post update] |
| tests.cpp:71:2:71:2 | p | tests.cpp:72:2:72:2 | p |
| tests.cpp:72:2:72:2 | p | tests.cpp:73:2:73:2 | p |
| tests.cpp:73:2:73:2 | p | tests.cpp:74:2:74:2 | p |
| tests.cpp:73:2:73:2 | p | tests.cpp:74:2:74:2 | p |
| tests.cpp:74:2:74:2 | p | tests.cpp:75:2:75:2 | p |
| tests.cpp:75:2:75:2 | p | tests.cpp:76:2:76:2 | p |
| tests.cpp:76:2:76:2 | p | tests.cpp:77:2:77:2 | p |
| tests.cpp:77:2:77:2 | p | tests.cpp:78:2:78:2 | p |
| tests.cpp:84:23:84:43 | XercesDOMParser output argument | tests.cpp:87:2:87:2 | p |
| tests.cpp:91:23:91:43 | XercesDOMParser output argument | tests.cpp:98:2:98:2 | p |
| tests.cpp:103:24:103:44 | XercesDOMParser output argument | tests.cpp:106:3:106:3 | q |
| tests.cpp:118:24:118:44 | XercesDOMParser output argument | tests.cpp:122:3:122:3 | q |
| tests.cpp:130:39:130:39 | p | tests.cpp:131:2:131:2 | p |
| tests.cpp:134:39:134:39 | p | tests.cpp:135:2:135:2 | p |
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:144:18:144:18 | q |
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:146:18:146:18 | q |
| tests.cpp:144:18:144:18 | q | tests.cpp:130:39:130:39 | p |
| tests.cpp:146:18:146:18 | q | tests.cpp:134:39:134:39 | p |
| tests.cpp:150:19:150:32 | call to createLSParser | tests.cpp:152:2:152:2 | p |
| tests.cpp:57:2:57:2 | p | tests.cpp:58:2:58:2 | p |
| tests.cpp:58:2:58:2 | p | tests.cpp:59:2:59:2 | p |
| tests.cpp:59:2:59:2 | p | tests.cpp:60:2:60:2 | p |
| tests.cpp:66:23:66:43 | XercesDOMParser output argument | tests.cpp:69:2:69:2 | p |
| tests.cpp:73:23:73:43 | XercesDOMParser output argument | tests.cpp:80:2:80:2 | p |
| tests.cpp:85:24:85:44 | XercesDOMParser output argument | tests.cpp:88:3:88:3 | q |
| tests.cpp:100:24:100:44 | XercesDOMParser output argument | tests.cpp:104:3:104:3 | q |
| tests.cpp:112:39:112:39 | p | tests.cpp:113:2:113:2 | p |
| tests.cpp:116:39:116:39 | p | tests.cpp:117:2:117:2 | p |
| tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:126:18:126:18 | q |
| tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:128:18:128:18 | q |
| tests.cpp:126:18:126:18 | q | tests.cpp:112:39:112:39 | p |
| tests.cpp:128:18:128:18 | q | tests.cpp:116:39:116:39 | p |
nodes
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:35:2:35:2 | p | semmle.label | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:49:2:49:2 | p | semmle.label | p |
| tests.cpp:53:19:53:19 | VariableAddress [post update] | semmle.label | VariableAddress [post update] |
| tests.cpp:53:23:53:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests2.cpp:20:17:20:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:22:2:22:2 | p | semmle.label | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:37:2:37:2 | p | semmle.label | p |
| tests3.cpp:23:21:23:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:25:2:25:2 | p | semmle.label | p |
| tests3.cpp:60:21:60:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:63:2:63:2 | p | semmle.label | p |
| tests3.cpp:67:21:67:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:70:2:70:2 | p | semmle.label | p |
| tests4.cpp:26:34:26:48 | (int)... | semmle.label | (int)... |
| tests4.cpp:36:34:36:50 | (int)... | semmle.label | (int)... |
| tests4.cpp:46:34:46:68 | ... \| ... | semmle.label | ... \| ... |
| tests4.cpp:77:34:77:38 | flags | semmle.label | flags |
| tests4.cpp:130:39:130:55 | (int)... | semmle.label | (int)... |
| tests.cpp:15:23:15:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:17:2:17:2 | p | semmle.label | p |
| tests.cpp:28:23:28:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:31:2:31:2 | p | semmle.label | p |
| tests.cpp:35:19:35:19 | VariableAddress [post update] | semmle.label | VariableAddress [post update] |
| tests.cpp:35:23:35:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:37:2:37:2 | p | semmle.label | p |
| tests.cpp:38:2:38:2 | p | semmle.label | p |
| tests.cpp:39:2:39:2 | p | semmle.label | p |
| tests.cpp:51:19:51:19 | VariableAddress [post update] | semmle.label | VariableAddress [post update] |
| tests.cpp:51:23:51:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:53:2:53:2 | p | semmle.label | p |
| tests.cpp:54:2:54:2 | p | semmle.label | p |
| tests.cpp:55:2:55:2 | p | semmle.label | p |
| tests.cpp:56:2:56:2 | p | semmle.label | p |
| tests.cpp:56:2:56:2 | p | semmle.label | p |
| tests.cpp:57:2:57:2 | p | semmle.label | p |
| tests.cpp:69:19:69:19 | VariableAddress [post update] | semmle.label | VariableAddress [post update] |
| tests.cpp:69:23:69:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:71:2:71:2 | p | semmle.label | p |
| tests.cpp:72:2:72:2 | p | semmle.label | p |
| tests.cpp:73:2:73:2 | p | semmle.label | p |
| tests.cpp:74:2:74:2 | p | semmle.label | p |
| tests.cpp:74:2:74:2 | p | semmle.label | p |
| tests.cpp:75:2:75:2 | p | semmle.label | p |
| tests.cpp:76:2:76:2 | p | semmle.label | p |
| tests.cpp:77:2:77:2 | p | semmle.label | p |
| tests.cpp:78:2:78:2 | p | semmle.label | p |
| tests.cpp:84:23:84:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:87:2:87:2 | p | semmle.label | p |
| tests.cpp:91:23:91:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:98:2:98:2 | p | semmle.label | p |
| tests.cpp:103:24:103:44 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:106:3:106:3 | q | semmle.label | q |
| tests.cpp:118:24:118:44 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:122:3:122:3 | q | semmle.label | q |
| tests.cpp:130:39:130:39 | p | semmle.label | p |
| tests.cpp:131:2:131:2 | p | semmle.label | p |
| tests.cpp:134:39:134:39 | p | semmle.label | p |
| tests.cpp:135:2:135:2 | p | semmle.label | p |
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:144:18:144:18 | q | semmle.label | q |
| tests.cpp:146:18:146:18 | q | semmle.label | q |
| tests.cpp:150:19:150:32 | call to createLSParser | semmle.label | call to createLSParser |
| tests.cpp:152:2:152:2 | p | semmle.label | p |
| tests.cpp:58:2:58:2 | p | semmle.label | p |
| tests.cpp:59:2:59:2 | p | semmle.label | p |
| tests.cpp:60:2:60:2 | p | semmle.label | p |
| tests.cpp:66:23:66:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:69:2:69:2 | p | semmle.label | p |
| tests.cpp:73:23:73:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:80:2:80:2 | p | semmle.label | p |
| tests.cpp:85:24:85:44 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:88:3:88:3 | q | semmle.label | q |
| tests.cpp:100:24:100:44 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:104:3:104:3 | q | semmle.label | q |
| tests.cpp:112:39:112:39 | p | semmle.label | p |
| tests.cpp:113:2:113:2 | p | semmle.label | p |
| tests.cpp:116:39:116:39 | p | semmle.label | p |
| tests.cpp:117:2:117:2 | p | semmle.label | p |
| tests.cpp:122:23:122:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:126:18:126:18 | q | semmle.label | q |
| tests.cpp:128:18:128:18 | q | semmle.label | q |
subpaths
#select
| tests.cpp:35:2:35:2 | p | tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:33:23:33:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:49:2:49:2 | p | tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:46:23:46:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:57:2:57:2 | p | tests.cpp:53:23:53:43 | XercesDOMParser output argument | tests.cpp:57:2:57:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:53:23:53:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:74:2:74:2 | p | tests.cpp:69:23:69:43 | XercesDOMParser output argument | tests.cpp:74:2:74:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:69:23:69:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:78:2:78:2 | p | tests.cpp:69:23:69:43 | XercesDOMParser output argument | tests.cpp:78:2:78:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:69:23:69:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:87:2:87:2 | p | tests.cpp:84:23:84:43 | XercesDOMParser output argument | tests.cpp:87:2:87:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:84:23:84:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:98:2:98:2 | p | tests.cpp:91:23:91:43 | XercesDOMParser output argument | tests.cpp:98:2:98:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:91:23:91:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:106:3:106:3 | q | tests.cpp:103:24:103:44 | XercesDOMParser output argument | tests.cpp:106:3:106:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:103:24:103:44 | XercesDOMParser output argument | XML parser |
| tests.cpp:122:3:122:3 | q | tests.cpp:118:24:118:44 | XercesDOMParser output argument | tests.cpp:122:3:122:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:118:24:118:44 | XercesDOMParser output argument | XML parser |
| tests.cpp:131:2:131:2 | p | tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:131:2:131:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:140:23:140:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:135:2:135:2 | p | tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:135:2:135:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:140:23:140:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:152:2:152:2 | p | tests.cpp:150:19:150:32 | call to createLSParser | tests.cpp:152:2:152:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:150:19:150:32 | call to createLSParser | XML parser |
| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser |
| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser |
| tests3.cpp:25:2:25:2 | p | tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:23:21:23:53 | call to createXMLReader | XML parser |
| tests3.cpp:63:2:63:2 | p | tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:60:21:60:53 | call to createXMLReader | XML parser |
| tests3.cpp:70:2:70:2 | p | tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:67:21:67:53 | call to createXMLReader | XML parser |
| tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:26:34:26:48 | (int)... | XML parser |
| tests4.cpp:36:34:36:50 | (int)... | tests4.cpp:36:34:36:50 | (int)... | tests4.cpp:36:34:36:50 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:36:34:36:50 | (int)... | XML parser |
| tests4.cpp:46:34:46:68 | ... \| ... | tests4.cpp:46:34:46:68 | ... \| ... | tests4.cpp:46:34:46:68 | ... \| ... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:46:34:46:68 | ... \| ... | XML parser |
| tests4.cpp:77:34:77:38 | flags | tests4.cpp:77:34:77:38 | flags | tests4.cpp:77:34:77:38 | flags | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:77:34:77:38 | flags | XML parser |
| tests4.cpp:130:39:130:55 | (int)... | tests4.cpp:130:39:130:55 | (int)... | tests4.cpp:130:39:130:55 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:130:39:130:55 | (int)... | XML parser |
| tests.cpp:17:2:17:2 | p | tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:15:23:15:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:31:2:31:2 | p | tests.cpp:28:23:28:43 | XercesDOMParser output argument | tests.cpp:31:2:31:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:28:23:28:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:39:2:39:2 | p | tests.cpp:35:23:35:43 | XercesDOMParser output argument | tests.cpp:39:2:39:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:35:23:35:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:56:2:56:2 | p | tests.cpp:51:23:51:43 | XercesDOMParser output argument | tests.cpp:56:2:56:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:51:23:51:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:60:2:60:2 | p | tests.cpp:51:23:51:43 | XercesDOMParser output argument | tests.cpp:60:2:60:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:51:23:51:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:69:2:69:2 | p | tests.cpp:66:23:66:43 | XercesDOMParser output argument | tests.cpp:69:2:69:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:66:23:66:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:80:2:80:2 | p | tests.cpp:73:23:73:43 | XercesDOMParser output argument | tests.cpp:80:2:80:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:73:23:73:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:88:3:88:3 | q | tests.cpp:85:24:85:44 | XercesDOMParser output argument | tests.cpp:88:3:88:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:85:24:85:44 | XercesDOMParser output argument | XML parser |
| tests.cpp:104:3:104:3 | q | tests.cpp:100:24:100:44 | XercesDOMParser output argument | tests.cpp:104:3:104:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:100:24:100:44 | XercesDOMParser output argument | XML parser |
| tests.cpp:113:2:113:2 | p | tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:113:2:113:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:122:23:122:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:117:2:117:2 | p | tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:117:2:117:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:122:23:122:43 | XercesDOMParser output argument | XML parser |

View File

@@ -1,32 +1,14 @@
// test cases for rule CWE-611
// test cases for rule CWE-611 (XercesDOMParser)
#include "tests.h"
// ---
class SecurityManager;
class InputSource;
class AbstractDOMParser {
public:
AbstractDOMParser();
void setDisableDefaultEntityResolution(bool); // default is false
void setCreateEntityReferenceNodes(bool); // default is true
void setSecurityManager(SecurityManager *const manager);
void parse(const InputSource &data);
};
class XercesDOMParser: public AbstractDOMParser {
public:
XercesDOMParser();
};
class DOMLSParser : public AbstractDOMParser {
};
DOMLSParser *createLSParser();
// ---
void test1(InputSource &data) {
@@ -145,26 +127,3 @@ void test10(InputSource &data) {
test10_doParseC(p, data);
test10_doParseC(q, data);
}
void test11(InputSource &data) {
DOMLSParser *p = createLSParser();
p->parse(data); // BAD (parser not correctly configured)
}
void test12(InputSource &data) {
DOMLSParser *p = createLSParser();
p->setDisableDefaultEntityResolution(true);
p->parse(data); // GOOD
}
DOMLSParser *g_p1 = createLSParser();
DOMLSParser *g_p2 = createLSParser();
InputSource *g_data;
void test13() {
g_p1->setDisableDefaultEntityResolution(true);
g_p1->parse(*g_data); // GOOD
g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
}

View File

@@ -1,2 +1,26 @@
// library functions for rule CWE-611
// library/common functions for rule CWE-611
#define NULL (0)
class SecurityManager;
class InputSource;
class AbstractDOMParser {
public:
AbstractDOMParser();
void setDisableDefaultEntityResolution(bool); // default is false
void setCreateEntityReferenceNodes(bool); // default is true
void setSecurityManager(SecurityManager *const manager);
void parse(const InputSource &data);
};
typedef unsigned int XMLCh;
class XMLUni
{
public:
static const XMLCh fgXercesDisableDefaultEntityResolution[];
static const XMLCh fgXercesHarmlessOption[];
};

View File

@@ -0,0 +1,46 @@
// test cases for rule CWE-611 (SAXParser)
#include "tests.h"
// ---
class SAXParser
{
public:
SAXParser();
void setDisableDefaultEntityResolution(bool); // default is false
void setSecurityManager(SecurityManager *const manager);
void parse(const InputSource &data);
};
// ---
void test2_1(InputSource &data) {
SAXParser *p = new SAXParser();
p->parse(data); // BAD (parser not correctly configured)
}
void test2_2(InputSource &data) {
SAXParser *p = new SAXParser();
p->setDisableDefaultEntityResolution(true);
p->parse(data); // GOOD
}
void test2_3(InputSource &data) {
SAXParser *p = new SAXParser();
bool v = false;
p->setDisableDefaultEntityResolution(v);
p->parse(data); // BAD (parser not correctly configured)
}
void test2_4(InputSource &data) {
SAXParser *p = new SAXParser();
bool v = true;
p->setDisableDefaultEntityResolution(v);
p->parse(data); // GOOD
}

View File

@@ -0,0 +1,82 @@
// test cases for rule CWE-611 (SAX2XMLReader)
#include "tests.h"
// ---
class SAX2XMLReader
{
public:
void setFeature(const XMLCh *feature, bool value);
void parse(const InputSource &data);
};
class XMLReaderFactory
{
public:
static SAX2XMLReader *createXMLReader();
};
// ---
void test3_1(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}
void test3_2(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
p->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p->parse(data); // GOOD
}
SAX2XMLReader *p_3_3 = XMLReaderFactory::createXMLReader();
void test3_3(InputSource &data) {
p_3_3->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}
SAX2XMLReader *p_3_4 = XMLReaderFactory::createXMLReader();
void test3_4(InputSource &data) {
p_3_4->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p_3_4->parse(data); // GOOD
}
SAX2XMLReader *p_3_5 = XMLReaderFactory::createXMLReader();
void test3_5_init() {
p_3_5->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
}
void test3_5(InputSource &data) {
test3_5_init();
p_3_5->parse(data); // GOOD
}
void test3_6(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
p->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured)
}
void test3_7(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
p->setFeature(XMLUni::fgXercesHarmlessOption, true);
p->parse(data); // BAD (parser not correctly configured)
}
void test3_8(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
const XMLCh *feature = XMLUni::fgXercesDisableDefaultEntityResolution;
p->setFeature(feature, true);
p->parse(data); // GOOD
}

View File

@@ -0,0 +1,135 @@
// test cases for rule CWE-611 (libxml2)
#include "tests.h"
// ---
enum xmlParserOption
{
XML_PARSE_NOENT = 2,
XML_PARSE_DTDLOAD = 4,
XML_PARSE_OPTION_HARMLESS = 8
};
class xmlDoc;
xmlDoc *xmlReadFile(const char *fileName, const char *encoding, int flags);
xmlDoc *xmlReadMemory(const char *ptr, int sz, const char *url, const char *encoding, int flags);
void xmlFreeDoc(xmlDoc *ptr);
// ---
void test4_1(const char *fileName) {
xmlDoc *p;
p = xmlReadFile(fileName, NULL, XML_PARSE_NOENT); // BAD (parser not correctly configured)
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_2(const char *fileName) {
xmlDoc *p;
p = xmlReadFile(fileName, NULL, XML_PARSE_DTDLOAD); // BAD (parser not correctly configured)
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_3(const char *fileName) {
xmlDoc *p;
p = xmlReadFile(fileName, NULL, XML_PARSE_NOENT | XML_PARSE_DTDLOAD); // BAD (parser not correctly configured)
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_4(const char *fileName) {
xmlDoc *p;
p = xmlReadFile(fileName, NULL, 0); // GOOD
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_5(const char *fileName) {
xmlDoc *p;
p = xmlReadFile(fileName, NULL, XML_PARSE_OPTION_HARMLESS); // GOOD
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_6(const char *fileName) {
xmlDoc *p;
int flags = XML_PARSE_NOENT;
p = xmlReadFile(fileName, NULL, flags); // BAD (parser not correctly configured)
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_7(const char *fileName) {
xmlDoc *p;
int flags = 0;
p = xmlReadFile(fileName, NULL, flags); // GOOD
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_8(const char *fileName) {
xmlDoc *p;
int flags = XML_PARSE_OPTION_HARMLESS;
p = xmlReadFile(fileName, NULL, flags | XML_PARSE_NOENT); // BAD (parser not correctly configured) [NOT DETECTED]
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_9(const char *fileName) {
xmlDoc *p;
int flags = XML_PARSE_NOENT;
p = xmlReadFile(fileName, NULL, flags | XML_PARSE_OPTION_HARMLESS); // BAD (parser not correctly configured) [NOT DETECTED]
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_10(const char *ptr, int sz) {
xmlDoc *p;
p = xmlReadMemory(ptr, sz, "", NULL, 0); // GOOD
if (p != NULL)
{
xmlFreeDoc(p);
}
}
void test4_11(const char *ptr, int sz) {
xmlDoc *p;
p = xmlReadMemory(ptr, sz, "", NULL, XML_PARSE_DTDLOAD); // BAD (parser not correctly configured)
if (p != NULL)
{
xmlFreeDoc(p);
}
}

View File

@@ -0,0 +1,78 @@
// test cases for rule CWE-611 (createLSParser)
#include "tests.h"
// ---
class DOMConfiguration {
public:
void setParameter(const XMLCh *parameter, bool value);
};
class DOMLSParser {
public:
DOMConfiguration *getDomConfig();
void parse(const InputSource &data);
};
class DOMImplementationLS {
public:
DOMLSParser *createLSParser();
};
// ---
void test5_1(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}
void test5_2(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p->parse(data); // GOOD
}
void test5_3(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}
void test5_4(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
DOMConfiguration *cfg = p->getDomConfig();
cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p->parse(data); // GOOD
}
void test5_5(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
DOMConfiguration *cfg = p->getDomConfig();
cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}
DOMImplementationLS *g_impl;
DOMLSParser *g_p1, *g_p2;
InputSource *g_data;
void test5_6_init() {
g_p1 = g_impl->createLSParser();
g_p1->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
g_p2 = g_impl->createLSParser();
}
void test5_6() {
test5_6_init();
g_p1->parse(*g_data); // GOOD
g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
}

View File

@@ -1,3 +1,5 @@
## 1.1.2
## 1.1.1
## 1.1.0

View File

@@ -0,0 +1 @@
## 1.1.2

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.1
lastReleaseVersion: 1.1.2

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.1.1
version: 1.1.2
groups:
- csharp
- solorigate

View File

@@ -1,3 +1,5 @@
## 1.1.2
## 1.1.1
## 1.1.0

View File

@@ -0,0 +1 @@
## 1.1.2

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.1
lastReleaseVersion: 1.1.2

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.1.1
version: 1.1.2
groups:
- csharp
- solorigate

View File

@@ -1,3 +1,5 @@
## 0.2.1
## 0.2.0
### Breaking Changes

View File

@@ -0,0 +1 @@
## 0.2.1

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.2.0
lastReleaseVersion: 0.2.1

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 0.2.0
version: 0.2.1
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -498,23 +498,35 @@ private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuratio
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(ContentSet cs |
readSet(node1, cs, node2, config) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
pragma[inline]
bindingset[c]
private predicate clearsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
clearsContentCached(n.asNode(), cs) and
c = cs.getAReadContent()
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
// inline to reduce fan-out via `getAReadContent`
bindingset[c]
private predicate expectsContentEx(NodeEx n, Content c) {
exists(ContentSet cs |
expectsContentCached(n.asNode(), cs) and
pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent()
)
}
pragma[nomagic]
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
@@ -793,7 +805,7 @@ private module Stage1 {
* by `revFlow`.
*/
pragma[nomagic]
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
revFlowConsCand(c, conf) and
revFlowStore(c, _, _, conf)
}
@@ -891,7 +903,7 @@ private module Stage1 {
pragma[nomagic]
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
read(n1, c, n2, pragma[only_bind_into](config)) and
revFlow(n2, pragma[only_bind_into](config))
}
@@ -1181,11 +1193,26 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
expectsContentEx(node, c)
)
}
bindingset[node, state, ap, config]
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
exists(ap) and
not stateBarrier(node, state, config)
not stateBarrier(node, state, config) and
(
notExpectsContent(node)
or
ap = true and
expectsContentCand(node, config)
)
}
bindingset[ap, contentType]
@@ -1646,10 +1673,24 @@ private module Stage2 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -1740,7 +1781,8 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends NodeEx {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _)
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
}
}
@@ -1979,6 +2021,16 @@ private module Stage3 {
clearContent(node, ap.getHead().getContent(), config)
}
pragma[nomagic]
private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) {
exists(Content c |
PrevStage::revFlow(node, pragma[only_bind_into](config)) and
PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and
expectsContentEx(node, c) and
c = ap.getHead().getContent()
)
}
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
@@ -1987,7 +2039,12 @@ private module Stage3 {
exists(state) and
exists(config) and
not clear(node, ap, config) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and
(
notExpectsContent(node)
or
expectsContentCand(node, ap, config)
)
}
bindingset[ap, contentType]
@@ -2452,10 +2509,24 @@ private module Stage3 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3279,10 +3350,24 @@ private module Stage4 {
storeStepFwd(_, ap, tc, _, _, config)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepCand(_, ap, tc, _, _, config)
}
private predicate validAp(Ap ap, Configuration config) {
revFlow(_, _, _, _, ap, config) and ap instanceof ApNil
or
exists(TypedContent head, Ap tail |
consCand(head, tail, config) and
ap = apCons(head, tail)
)
}
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
revConsCand(tc, ap, config) and
validAp(ap, config)
}
pragma[noinline]
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
@@ -3351,17 +3436,28 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, DataFlowCallable c, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, _, _) and
Stage4::revFlow(n, state, true, _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(DataFlowCallable c |
Stage4::parameterMayFlowThrough(_, c, apa, config) and
nodeMayUseSummary0(n, c, state, apa, config)
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
@@ -4257,6 +4353,12 @@ private module Subpaths {
)
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
@@ -4264,15 +4366,13 @@ private module Subpaths {
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
par.getNodeEx() = p and
out0.getNodeEx() = o and
out0.getState() = sout and
out0.getAp() = apout and
(out = out0 or out = out0.projectToSink())
pathNode(out0, o, sout, _, _, apout, _, _)
|
out = out0 or out = out0.projectToSink()
)
}
@@ -4609,6 +4709,10 @@ private module FlowExploration {
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
@@ -4625,6 +4729,10 @@ private module FlowExploration {
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()

View File

@@ -328,6 +328,9 @@ private module Cached {
cached
predicate clearsContentCached(Node n, ContentSet c) { clearsContent(n, c) }
cached
predicate expectsContentCached(Node n, ContentSet c) { expectsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }

View File

@@ -421,7 +421,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
or
exists(Ssa::Definition def |
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
not FlowSummaryImpl::Private::Steps::summaryClearsContentArg(nodeFrom, _) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom) and
not LocalFlow::usesInstanceField(def)
)
or
@@ -1714,6 +1714,14 @@ predicate clearsContent(Node n, Content c) {
)
}
/**
* Holds if the value that is being tracked is expected to be stored inside content `c`
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
}
/**
* Holds if the node `n` is unreachable when the call context is `call`.
*/

View File

@@ -26,6 +26,10 @@ module Public {
string toString() {
exists(ContentSet c | this = TContentSummaryComponent(c) and result = c.toString())
or
exists(ContentSet c | this = TWithoutContentSummaryComponent(c) and result = "without " + c)
or
exists(ContentSet c | this = TWithContentSummaryComponent(c) and result = "with " + c)
or
exists(ArgumentPosition pos |
this = TParameterSummaryComponent(pos) and result = "parameter " + pos
)
@@ -43,6 +47,12 @@ module Public {
/** Gets a summary component for content `c`. */
SummaryComponent content(ContentSet c) { result = TContentSummaryComponent(c) }
/** Gets a summary component where data is not allowed to be stored in `c`. */
SummaryComponent withoutContent(ContentSet c) { result = TWithoutContentSummaryComponent(c) }
/** Gets a summary component where data must be stored in `c`. */
SummaryComponent withContent(ContentSet c) { result = TWithContentSummaryComponent(c) }
/** Gets a summary component for a parameter at position `pos`. */
SummaryComponent parameter(ArgumentPosition pos) { result = TParameterSummaryComponent(pos) }
@@ -216,9 +226,16 @@ module Public {
/**
* Holds if values stored inside `content` are cleared on objects passed as
* arguments at position `pos` to this callable.
*
* TODO: Remove once all languages support `WithoutContent` tokens.
*/
pragma[nomagic]
predicate clearsContent(ParameterPosition pos, ContentSet content) { none() }
/**
* Holds if the summary is auto generated.
*/
predicate isAutoGenerated() { none() }
}
}
@@ -234,7 +251,9 @@ module Private {
TContentSummaryComponent(ContentSet c) or
TParameterSummaryComponent(ArgumentPosition pos) or
TArgumentSummaryComponent(ParameterPosition pos) or
TReturnSummaryComponent(ReturnKind rk)
TReturnSummaryComponent(ReturnKind rk) or
TWithoutContentSummaryComponent(ContentSet c) or
TWithContentSummaryComponent(ContentSet c)
private TParameterSummaryComponent thisParam() {
result = TParameterSummaryComponent(instanceParameterPosition())
@@ -296,6 +315,23 @@ module Private {
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
preservesValue = preservesValue1.booleanAnd(preservesValue2)
)
or
exists(ParameterPosition ppos, ContentSet cs |
c.clearsContent(ppos, cs) and
input = SummaryComponentStack::push(SummaryComponent::withoutContent(cs), output) and
output = SummaryComponentStack::argument(ppos) and
preservesValue = true
)
}
private class MkClearStack extends RequiredSummaryComponentStack {
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
exists(SummarizedCallable sc, ParameterPosition ppos, ContentSet cs |
sc.clearsContent(ppos, cs) and
head = SummaryComponent::withoutContent(cs) and
tail = SummaryComponentStack::argument(ppos)
)
}
}
/**
@@ -378,10 +414,7 @@ module Private {
private newtype TSummaryNodeState =
TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or
TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } or
TSummaryNodeClearsContentState(ParameterPosition pos, boolean post) {
any(SummarizedCallable sc).clearsContent(pos, _) and post in [false, true]
}
TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) }
/**
* A state used to break up (complex) flow summaries into atomic flow steps.
@@ -428,12 +461,6 @@ module Private {
this = TSummaryNodeOutputState(s) and
result = "to write: " + s
)
or
exists(ParameterPosition pos, boolean post, string postStr |
this = TSummaryNodeClearsContentState(pos, post) and
(if post = true then postStr = " (post)" else postStr = "") and
result = "clear: " + pos + postStr
)
}
}
@@ -457,11 +484,6 @@ module Private {
not parameterReadState(c, state, _)
or
state.isOutputState(c, _)
or
exists(ParameterPosition pos |
c.clearsContent(pos, _) and
state = TSummaryNodeClearsContentState(pos, _)
)
}
pragma[noinline]
@@ -497,8 +519,6 @@ module Private {
parameterReadState(c, _, pos)
or
isParameterPostUpdate(_, c, pos)
or
c.clearsContent(pos, _)
}
private predicate callbackOutput(
@@ -506,7 +526,7 @@ module Private {
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
receiver = summaryNodeInputState(c, s.drop(1))
receiver = summaryNodeInputState(c, s.tail())
}
private predicate callbackInput(
@@ -514,7 +534,7 @@ module Private {
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
receiver = summaryNodeInputState(c, s.drop(1))
receiver = summaryNodeInputState(c, s.tail())
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
@@ -540,15 +560,21 @@ module Private {
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
n = summaryNodeInputState(c, s) and
(
exists(ContentSet cont | result = getContentType(cont) |
head = TContentSummaryComponent(cont) or
head = TWithContentSummaryComponent(cont)
)
or
exists(ContentSet cont |
head = TContentSummaryComponent(cont) and result = getContentType(cont)
head = TWithoutContentSummaryComponent(cont) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
)
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.drop(1))), rk)
s.tail())), rk)
)
)
or
@@ -567,16 +593,10 @@ module Private {
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.drop(1))), pos)
s.tail())), pos)
)
)
)
or
exists(SummarizedCallable c, ParameterPosition pos, ParamNode p |
n = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
p.isParameterOf(c, pos) and
result = getNodeType(p)
)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
@@ -602,9 +622,6 @@ module Private {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(c, pos)
or
pre = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
post = summaryNode(c, TSummaryNodeClearsContentState(pos, true))
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -628,8 +645,6 @@ module Private {
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
c.clearsContent(ppos, _)
or
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -658,9 +673,10 @@ module Private {
preservesValue = false and not summary(c, inputContents, outputContents, true)
)
or
exists(SummarizedCallable c, ParameterPosition pos |
pred.(ParamNode).isParameterOf(c, pos) and
succ = summaryNode(c, TSummaryNodeClearsContentState(pos, _)) and
exists(SummarizedCallable c, SummaryComponentStack s |
pred = summaryNodeInputState(c, s.tail()) and
succ = summaryNodeInputState(c, s) and
s.head() = [SummaryComponent::withContent(_), SummaryComponent::withoutContent(_)] and
preservesValue = true
)
}
@@ -671,7 +687,7 @@ module Private {
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.drop(1)) and
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
SummaryComponent::content(c) = s.head()
)
@@ -684,7 +700,7 @@ module Private {
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.drop(1)) and
succ = summaryNodeOutputState(sc, s.tail()) and
SummaryComponent::content(c) = s.head()
)
}
@@ -709,9 +725,22 @@ module Private {
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
exists(SummarizedCallable sc, ParameterPosition pos |
n = summaryNode(sc, TSummaryNodeClearsContentState(pos, true)) and
sc.clearsContent(pos, c)
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
}
/**
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
}
@@ -723,22 +752,6 @@ module Private {
sc = viableCallable(call)
}
/**
* Holds if values stored inside content `c` are cleared inside a
* callable to which `arg` is an argument.
*
* In such cases, it is important to prevent use-use flow out of
* `arg` (see comment for `summaryClearsContent`).
*/
pragma[nomagic]
predicate summaryClearsContentArg(ArgNode arg, ContentSet c) {
exists(DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, _) and
sc.clearsContent(ppos, c)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg) {
exists(ParameterPosition ppos, SummarizedCallable sc |
@@ -747,6 +760,27 @@ module Private {
)
}
/**
* Holds if use-use flow starting from `arg` should be prohibited.
*
* This is the case when `arg` is the argument of a call that targets a
* flow summary where the corresponding parameter either clears contents
* or expects contents.
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg) {
exists(ParamNode p, Node mid, ParameterPosition ppos, Node ret |
p = summaryArgParam0(_, arg) and
p.isParameterOf(_, ppos) and
summaryLocalStep(p, mid, true) and
summaryLocalStep(mid, ret, true) and
isParameterPostUpdate(ret, _, ppos)
|
summaryClearsContent(mid, _) or
summaryExpectsContent(mid, _)
)
}
pragma[nomagic]
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
exists(DataFlowCall call |
@@ -898,6 +932,8 @@ module Private {
kind = "taint" and preservesValue = false
)
}
override predicate isAutoGenerated() { summaryElement(this, _, _, _, true) }
}
/** Holds if component `c` of specification `spec` cannot be parsed. */
@@ -1052,9 +1088,13 @@ module Private {
preservesValue = false and result = "taint"
}
private string renderGenerated(RelevantSummarizedCallable c) {
if c.isAutoGenerated() then result = "generated:" else result = ""
}
/**
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind",
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;(generated:)?kind",
* ext is hardcoded to empty.
*/
query predicate summary(string csv) {
@@ -1065,7 +1105,7 @@ module Private {
c.relevantSummary(input, output, preservesValue) and
csv =
c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) +
";" + renderKind(preservesValue)
";" + renderGenerated(c) + renderKind(preservesValue)
)
}
}
@@ -1141,6 +1181,10 @@ module Private {
Private::Steps::summaryClearsContent(a.asNode(), c) and
b = a and
value = "clear (" + c + ")"
or
Private::Steps::summaryExpectsContent(a.asNode(), c) and
b = a and
value = "expect (" + c + ")"
)
or
summaryPostUpdateNode(b.asNode(), a.asNode()) and

View File

@@ -49,7 +49,7 @@ private predicate unknownSign(Expr e) {
or
exists(LongLiteral lit | lit = e and not exists(lit.getValue().toFloat()))
or
exists(CastExpr cast, Type fromtyp |
exists(CastingExpr cast, Type fromtyp |
cast = e and
fromtyp = cast.getSourceType() and
not fromtyp instanceof NumericOrCharType

View File

@@ -29,6 +29,8 @@ module Private {
class CastExpr = RU::ExprNode::CastExpr;
class CastingExpr = CastExpr;
class Type = CS::Type;
class Expr = CS::ControlFlow::Nodes::ExprNode;

View File

@@ -175,8 +175,8 @@ class Call extends DotNet::Call, Expr, @call {
* - Line 10: The static target is `Type.InvokeMember()`, whereas the run-time targets
* are both `A.M()` and `B.M()`.
*
* - Line 16: There is no static target (delegate call) but the delegate `i => { }` (line
* 20) is a run-time target.
* - Line 16: There is no static target (delegate call) but the delegate `i => { }`
* (line 20) is a run-time target.
*/
override Callable getARuntimeTarget() {
exists(DispatchCall dc | dc.getCall() = this | result = dc.getADynamicTarget())

View File

@@ -55,7 +55,7 @@ private class SystemCollectionsIEnumerableClearFlow extends SummarizedCallable {
}
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
pos.isThisParameter() and
(if this.(Modifiable).isStatic() then pos.getPosition() = 0 else pos.isThisParameter()) and
content instanceof DataFlow::ElementContent
}
}

View File

@@ -1,6 +1,6 @@
/**
* @name Potentially incorrect CompareTo(...) signature
* @description The declaring type of a method with signature 'CompareTo(T)' does not implement 'IComparable<T>'.
* @description The declaring type of a method with signature `CompareTo(T)` does not implement `IComparable<T>`.
* @kind problem
* @problem.severity warning
* @precision medium

View File

@@ -1,3 +1,5 @@
## 0.1.2
## 0.1.1
## 0.1.0

View File

@@ -1,6 +1,6 @@
/**
* @name Incorrect parameter name in documentation
* @description The parameter name given in a '<param>' tag does not exist. Rename the parameter or
* @description The parameter name given in a `<param>` tag does not exist. Rename the parameter or
* change the name in the documentation to ensure that they are the same.
* @kind problem
* @problem.severity recommendation

View File

@@ -1,6 +1,6 @@
/**
* @name Incorrect type parameter name in documentation
* @description The type parameter name given in a '<typeparam>' tag does not exist. Rename the parameter or
* @description The type parameter name given in a `<typeparam>` tag does not exist. Rename the parameter or
* change the name in the documentation to ensure that they are the same.
* @kind problem
* @problem.severity recommendation

View File

@@ -1,6 +1,6 @@
/**
* @name Missing documentation for exception
* @description Exceptions thrown by the method should be documented using '<exception cref="..."> </exception>' tags.
* @description Exceptions thrown by the method should be documented using `<exception cref="..."> </exception>` tags.
* Ensure that the correct type of the exception is given in the 'cref' attribute.
* @kind problem
* @problem.severity recommendation

View File

@@ -1,6 +1,6 @@
/**
* @name Missing documentation for parameter
* @description All parameters should be documented using '<param name="..."> </param>' tags.
* @description All parameters should be documented using `<param name="..."> </param>` tags.
* Ensure that the name attribute matches the name of the parameter.
* @kind problem
* @problem.severity recommendation

View File

@@ -1,7 +1,7 @@
/**
* @name Missing documentation for return value
* @description The method returns a value, but the return value is not documented using
* a '<returns>' tag.
* a `<returns>` tag.
* @kind problem
* @problem.severity recommendation
* @precision low

View File

@@ -1,6 +1,6 @@
/**
* @name Missing a summary in documentation comment
* @description The documentation comment does not contain a '<summary>' tag.
* @description The documentation comment does not contain a `<summary>` tag.
* @kind problem
* @problem.severity recommendation
* @precision high

View File

@@ -1,6 +1,6 @@
/**
* @name Missing documentation for type parameter
* @description All type parameters should be documented using '<typeparam name="..."> </typeparam>' tags.
* @description All type parameters should be documented using `<typeparam name="..."> </typeparam>` tags.
* Ensure that the 'name' attribute matches the name of the type parameter.
* @kind problem
* @problem.severity recommendation

View File

@@ -0,0 +1,18 @@
/**
* @id csharp/summary/framework-coverage
* @name Metrics of framework coverage
* @description Expose metrics for the number of API endpoints covered by CSV models.
* @kind metric
* @tags summary
*/
import csharp
import semmle.code.csharp.dataflow.ExternalFlow
from string namespaceAndType, int rows
where
exists(string namespace, string type |
namespaceAndType = namespace + ";" + type and
rows = strictsum(int n, string kind | modelCoverage(namespace, _, kind, type, n) | n)
)
select namespaceAndType, rows

View File

@@ -2,7 +2,7 @@
* @name XML injection
* @description Building an XML document from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
* @kind problem
* @kind path-problem
* @id cs/xml-injection
* @problem.severity error
* @security-severity 8.8
@@ -12,6 +12,7 @@
*/
import csharp
import DataFlow::PathGraph
import semmle.code.csharp.security.dataflow.flowsources.Remote
import semmle.code.csharp.frameworks.system.Xml
@@ -45,6 +46,6 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
}
}
from TaintTrackingConfiguration c, DataFlow::Node source, DataFlow::Node sink
where c.hasFlow(source, sink)
select sink, "$@ flows to here and is inserted as XML.", source, "User-provided value"
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink
where c.hasFlowPath(source, sink)
select sink, source, sink, "$@ flows to here and is inserted as XML.", source, "User-provided value"

View File

@@ -71,7 +71,7 @@ if (version != "latest"):
cmd.append(version)
run_cmd(cmd)
sdk_version = '6.0.101'
sdk_version = '6.0.202'
print("\n* Creating new global.json file and setting SDK to " + sdk_version)
run_cmd(['dotnet', 'new', 'globaljson', '--force', '--sdk-version', sdk_version, '--output', workDir])

View File

@@ -2,7 +2,7 @@
* @name External libraries
* @description A list of external libraries used in the code
* @kind metric
* @tags summary
* @tags summary telemetry
* @id csharp/telemetry/external-libs
*/

View File

@@ -2,7 +2,7 @@
* @name Supported sinks in external libraries
* @description A list of 3rd party APIs detected as sinks. Excludes APIs exposed by test libraries.
* @kind metric
* @tags summary
* @tags summary telemetry
* @id csharp/telemetry/supported-external-api-sinks
*/

View File

@@ -2,7 +2,7 @@
* @name Supported sources in external libraries
* @description A list of 3rd party APIs detected as sources. Excludes APIs exposed by test libraries.
* @kind metric
* @tags summary
* @tags summary telemetry
* @id csharp/telemetry/supported-external-api-sources
*/

View File

@@ -2,7 +2,7 @@
* @name Supported flow steps in external libraries
* @description A list of 3rd party APIs detected as flow steps. Excludes APIs exposed by test libraries.
* @kind metric
* @tags summary
* @tags summary telemetry
* @id csharp/telemetry/supported-external-api-taint
*/

View File

@@ -2,7 +2,7 @@
* @name Usage of unsupported APIs coming from external libraries
* @description A list of 3rd party APIs used in the codebase. Excludes APIs exposed by test libraries.
* @kind metric
* @tags summary
* @tags summary telemetry
* @id csharp/telemetry/unsupported-external-api
*/

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