Compare commits

...

1308 Commits

Author SHA1 Message Date
Felicity Chapman
770326e770 Merge pull request #12321 from github/fc-7775-docs-update
CodeQL extension for VS Code docs update
2023-02-28 14:59:46 +00:00
Felicity Chapman
a7d221cdab Update docs/codeql/reusables/beta-note-mrva.rst 2023-02-28 14:12:57 +00:00
Felicity Chapman
aba7440293 Update docs/codeql/codeql-for-visual-studio-code/running-codeql-queries-at-scale-with-mrva.rst
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2023-02-28 12:29:16 +00:00
Felicity Chapman
832dc27b08 Update docs/codeql/codeql-for-visual-studio-code/running-codeql-queries-at-scale-with-mrva.rst
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2023-02-28 12:22:26 +00:00
Felicity Chapman
0af529ed7b Apply suggestions from code review
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2023-02-28 11:12:29 +00:00
Felicity Chapman
b21253732b Update for review feedback 2023-02-28 09:58:51 +00:00
Felicity Chapman
1d13811e46 Revise troubleshooting article 2023-02-27 16:42:07 +00:00
Felicity Chapman
8e4eb9ad46 Tweaks to mention variant analysis in related articles 2023-02-27 16:21:09 +00:00
Felicity Chapman
49ec539b60 Updates following initial PM review 2023-02-27 16:07:28 +00:00
Felicity Chapman
29802af647 Fix typo in heading 2023-02-27 15:06:19 +00:00
Felicity Chapman
9bee9c003a Apply suggestions from code review
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2023-02-27 14:58:17 +00:00
Felicity Chapman
70ed029d0e More updates 2023-02-27 12:41:53 +00:00
Felicity Chapman
8af12071e1 First draft with bare bones 2023-02-24 21:39:16 +00:00
Felicity Chapman
874c362961 Add basic framework of new articles 2023-02-24 17:14:49 +00:00
Nick Rolfe
44dc5a1f0b Merge pull request #12209 from github/release-prep/2.12.3
Release preparation for version 2.12.3
2023-02-16 13:25:19 +00:00
Nick Rolfe
b4d59ff932 Go: changenote grammar tweaks 2023-02-16 12:07:47 +00:00
github-actions[bot]
b0315119c6 Release preparation for version 2.12.3 2023-02-16 11:49:06 +00:00
Chris Smowton
180246b99c Merge pull request #12197 from smowton/smowton/admin/go-120-features
Go: complete Go 1.20 support
2023-02-16 08:12:02 +00:00
Owen Mansel-Chan
45c1537f06 Merge pull request #12198 from github/smowton/admin/update-change-note
Update Twirp change note to new style
2023-02-15 21:54:48 +00:00
Rasmus Wriedt Larsen
ee5382d8a6 Merge pull request #12193 from RasmusWL/import-resolution-fixup
Python: Fix `from <pkg> import *` import resolution
2023-02-15 20:13:24 +01:00
Chris Smowton
3ce7fafb67 Fix unsafe test routine name 2023-02-15 19:05:01 +00:00
Chris Smowton
14655e1d8c Autoformat go 2023-02-15 18:41:14 +00:00
Chris Smowton
261a1348f0 Update Twirp change note to new style 2023-02-15 18:37:50 +00:00
Chris Smowton
c65fd69374 Add change note 2023-02-15 18:35:17 +00:00
Chris Smowton
233bd8ce8c Claim Go 1.20 support 2023-02-15 18:31:28 +00:00
Chris Smowton
7e7850374e Implement standard library models for Go 1.20 2023-02-15 18:29:49 +00:00
Chris Smowton
7d2b78b463 Note that all interface types are considered comparable as of Go 1.20 2023-02-15 17:15:00 +00:00
Rasmus Wriedt Larsen
c72dbc49fc Merge pull request #12165 from RasmusWL/crypto-updates
Python/Ruby/JS Crypto: Add a few algorithms + block modes
2023-02-15 14:35:40 +01:00
Rasmus Wriedt Larsen
7e16fa9cbe Python: Add change-note 2023-02-15 14:25:33 +01:00
Rasmus Wriedt Larsen
220f227707 Python: Add wrapper for isPreferredModuleForName
We talked about how it's annoying that we in 4 places have the same fix
`isPreferredModuleForName(<module>.getFile(), <name> + ["", ".__init__"])`
, and that it would be nice to have a simple wrapper predicate that
ensures we never forget to do the `+ ["", ".__init__"]` dance...

I had trouble coming up with a name for this (ironically), but
I think `getModuleFromName` is good enough.
2023-02-15 14:23:39 +01:00
Rasmus Wriedt Larsen
66c3529465 Python: Fix import * from __init__.py files 2023-02-15 14:10:37 +01:00
Rasmus Wriedt Larsen
df6039d6cf Python: Add import resolution regression 2023-02-15 13:50:27 +01:00
Rasmus Wriedt Larsen
e1ae3c3cfb Python: sys.exit if import resolution tests fail 2023-02-15 13:44:45 +01:00
Chris Smowton
368ca6cb30 Add test exercising Go 1.20 array conversions 2023-02-15 12:31:09 +00:00
Chris Smowton
2cd1e09a7e Merge pull request #12111 from smowton/smowton/feature/java-merge-classes-and-interfaces
Java: merge the @class and @interface database types and tables
2023-02-15 10:27:41 +00:00
Chris Smowton
5f0b1973ee Merge pull request #12188 from smowton/smowton/feature/go-1.20-support
Go: Upgrade extractor compiler and dependency versions
2023-02-15 10:06:01 +00:00
Paolo Tranquilli
4be2e431ea Merge pull request #12180 from github/redsun82/swift-codegen
Swift: some restructuring of codegen
2023-02-15 10:15:20 +01:00
Anders Schack-Mulligen
b52df0de0c Merge pull request #12191 from github/workflow/coverage/update
Update CSV framework coverage reports
2023-02-15 09:07:40 +01:00
Harry Maclean
fb14920281 Merge pull request #12056 from hmac/test-refactor 2023-02-15 17:34:25 +13:00
github-actions[bot]
5f07d1f385 Add changed framework coverage reports 2023-02-15 00:17:48 +00:00
Chris Smowton
194316d1c0 Accept test changes
Some diagnostics have been reworded for Go 1.20, and a standard library type parameter is visible to the TypeParamType test.
2023-02-14 18:33:53 +00:00
Chris Smowton
d075e016b2 Upgrade Go to 1.20 2023-02-14 17:59:18 +00:00
Chris Smowton
9e584eb241 Upgrade Go extractor compiler and dependency versions 2023-02-14 17:34:47 +00:00
Chris Smowton
62d10f91d8 Improve join ordering 2023-02-14 17:21:24 +00:00
Chris Smowton
d5f7ef08b7 Update stats 2023-02-14 17:21:24 +00:00
Chris Smowton
7f76d8ae55 Replace redundant use of Class or Interface 2023-02-14 17:21:24 +00:00
Chris Smowton
82a2f4349a Resolve a newly-introduced ambiguity
Also fix a simple redundancy noticed while debugging
2023-02-14 17:21:24 +00:00
Chris Smowton
f48d87ba55 Add deletions for removed tables 2023-02-14 17:21:24 +00:00
Chris Smowton
3514dd1e4d Java: merge the @class and @interface database types and tables
This will allow the extractor to emit class(id, ...) when all it knows about a class is its name, due to not having it available on the classpath. Previously it would have had to guess whether it belonged to @class or @interface, possibly introducing an inconsistency.
2023-02-14 17:21:23 +00:00
Jami
029e1d47fe Merge pull request #12081 from jcogs33/jcogs33/update-some-Files-sinks
Java: update `createTempDirectory` and `copy` "create-file" sinks
2023-02-14 10:53:17 -05:00
Taus
e40bb6ac87 Merge pull request #12029 from github/tausbn/python-clean-up-version-handling
Python: Clean up version handling
2023-02-14 16:40:09 +01:00
Taus
1b30043422 Python: Move change note to correct directory 2023-02-14 13:48:55 +00:00
Taus
4f7c598ffc Python: Add change note 2023-02-14 13:22:48 +00:00
Erik Krogh Kristensen
2f8c9a5a2c Merge pull request #12171 from erik-krogh/reg-dot
JS: dont recognize regexps that match dot as sanitizers
2023-02-14 14:10:44 +01:00
Erik Krogh Kristensen
e3e2df3247 Merge pull request #12166 from erik-krogh/more-html-san
JS: add `HtmlSanitizer` as a sanitizer DOMBasedXss
2023-02-14 14:09:56 +01:00
Taus
39516862c1 Merge remote-tracking branch 'origin/main' into tausbn/python-clean-up-version-handling 2023-02-14 13:07:40 +00:00
Erik Krogh Kristensen
028fcc7edf Merge pull request #11959 from erik-krogh/ssrfSan
JS: add encodeURIComponent as a sanitizer for request-forgery
2023-02-14 13:39:53 +01:00
Erik Krogh Kristensen
a498936f16 Merge pull request #12170 from erik-krogh/more-lib
JS: More library inputs
2023-02-14 13:38:00 +01:00
Erik Krogh Kristensen
bca3fa94fd Merge pull request #12159 from erik-krogh/express-ws
JS: add express-ws as a source
2023-02-14 13:36:33 +01:00
Joe Farebrother
f68083872d Merge pull request #12174 from joefarebrother/stubgen-name-conflicts
Java: Stub generator: Use fully qualified names to avoid conflicts
2023-02-14 10:10:24 +00:00
Paolo Tranquilli
81de500301 Swift: fix import not working in all python versions 2023-02-14 10:40:05 +01:00
Anders Schack-Mulligen
0600a2ba96 Merge pull request #12138 from aschackmull/java/gen-file-mark-perf
Java: Improve performance of GeneratedFileMarker.
2023-02-14 09:57:09 +01:00
Tony Torralba
935e22d10d Merge pull request #12139 from atorralba/atorralba/java/xxe-local-query
Java: Add local version of the XXE query
2023-02-14 09:54:36 +01:00
Paolo Tranquilli
8e079320f3 Swift: some restructuring of codegen
Loading of the schema and dbscheme has been moved to a separate
`loaders` package for better separation of concerns.
2023-02-14 09:53:02 +01:00
Michael Nebel
781aab3eb7 Merge pull request #11634 from michaelnebel/java/excludeinterfacemembers
Java: Exclude interface members from model generation.
2023-02-14 09:35:56 +01:00
erik-krogh
4140598769 update expected output for experimental query 2023-02-14 00:08:13 +01:00
erik-krogh
c17d057520 default to index.js when no main: is specified in package.json, and recognize more classes as library inputs 2023-02-13 21:24:41 +01:00
Joe Farebrother
0b722bfe30 Stub generator: Use fully qualified names to avoid conflicts 2023-02-13 17:09:32 +00:00
erik-krogh
68656274f4 dont recognize regexps that match dot as sanitizers 2023-02-13 17:36:51 +01:00
Jami Cogswell
e4c8387815 Java: update CaptureSinkModels.expected with read-file sink 2023-02-13 11:29:30 -05:00
Tony Torralba
1c57aa0456 Fix import locations 2023-02-13 17:13:01 +01:00
Tom Hvitved
8372ad9d84 Merge pull request #12169 from hvitved/util/numbers
Move `NumberUtils.qll` from Ruby into shared `util` pack
2023-02-13 16:37:51 +01:00
Tom Hvitved
2113c3c3d9 Ruby: Remove NumberUtils.qll 2023-02-13 15:59:50 +01:00
Tom Hvitved
29ce9bfe24 Util: Make some predicates private 2023-02-13 15:58:31 +01:00
Tom Hvitved
97f79602a9 Copy NumberUtils.qll from Ruby into shared util pack 2023-02-13 15:57:53 +01:00
erik-krogh
6192544fb4 add test for express-ws as a source 2023-02-13 15:26:50 +01:00
Jami Cogswell
1c3d4b98c8 Java: move change note 2023-02-13 09:15:31 -05:00
Jami Cogswell
191613e8bf Java: update change note 2023-02-13 09:11:53 -05:00
Owen Mansel-Chan
4fa484dad2 Merge pull request #12130 from owen-mc/go/port-integration-tests
Go: port integration tests
2023-02-13 13:49:59 +00:00
Rasmus Wriedt Larsen
39e50f745d Ruby: Fix .expected for CryptoAlgorithms 2023-02-13 14:21:12 +01:00
Kasper Svendsen
c66a44f2e2 Merge pull request #12162 from kaspersv/kaspersv/inline-late-docs
QLDocs: Document inline_late pragma
2023-02-13 13:35:28 +01:00
Anders Schack-Mulligen
e877b161d8 Merge pull request #12124 from hvitved/dataflow/stage1-dispatch
Data flow: Call context virtual dispatch pruning in stage 1
2023-02-13 13:13:43 +01:00
Owen Mansel-Chan
7ebe472cfe Move repo files into subfolder
This is so that the test-db doesn't get moved when all the repo files
are moved, which was causing some problems.
2023-02-13 11:59:38 +00:00
Owen Mansel-Chan
37d3793e87 Set LGTM_INDEX_IMPORT_PATH in two tests
This is needed for Dep and Glide
2023-02-13 11:59:38 +00:00
Owen Mansel-Chan
1f1e2dbf98 Make dep integration test linux-only
This is because there is no release of Dep for
MacOS (Arm).
2023-02-13 11:59:38 +00:00
Owen Mansel-Chan
3ee3acd8fd Make Glide integration test linux-only
This is because it is hard to install Glide on the other platforms.
2023-02-13 11:59:37 +00:00
Owen Mansel-Chan
e635140eae Add files needed for tests 2023-02-13 11:59:37 +00:00
Owen Mansel-Chan
f2c541a461 Delete build-sample test
This is adequately tested elsewhere.
2023-02-13 11:59:37 +00:00
Owen Mansel-Chan
f062a8d204 Copy LGTM integration tests over 2023-02-13 11:59:36 +00:00
Owen Mansel-Chan
947a9f12a1 Make DiagnosticsReporting.qll a library 2023-02-13 11:59:36 +00:00
Kasper Svendsen
11204987f1 Reword based on review comments 2023-02-13 12:49:50 +01:00
Michael Nebel
34c6b24882 Merge pull request #12147 from michaelnebel/csharp/relaxedshift
C# 11: Test of relaxed shift operator requirements.
2023-02-13 12:48:39 +01:00
Arthur Baars
457a2bb2a2 Merge pull request #12093 from aibaars/oneline-match
Ruby: add support for one-line pattern matches
2023-02-13 12:38:28 +01:00
Kasper Svendsen
ac54caac35 Update docs/codeql/ql-language-reference/annotations.rst
Co-authored-by: Philip Ginsbach <ginsbach@github.com>
2023-02-13 12:35:08 +01:00
Kasper Svendsen
426425a7ca Update docs/codeql/ql-language-reference/annotations.rst
Co-authored-by: Philip Ginsbach <ginsbach@github.com>
2023-02-13 12:34:50 +01:00
Chris Smowton
0537579b28 Merge pull request #12131 from owen-mc/go/named-type-location
Add `hasLocationInfo` for `Type`s
2023-02-13 11:33:50 +00:00
Erik Krogh Kristensen
2f404df17c Merge pull request #10782 from erik-krogh/rbPoly
Ruby: add library input as a source for `rb/polynomial-redos`
2023-02-13 12:26:07 +01:00
erik-krogh
b85bfc8ba6 add HtmlSanitizer as a sanitizer for DOMBasedXss 2023-02-13 11:57:29 +01:00
erik-krogh
c258e44772 add failing test for spurious edge through sanitizer 2023-02-13 11:49:57 +01:00
Erik Krogh Kristensen
26d5fb2412 Merge pull request #11824 from erik-krogh/secondMissAnchor
RB: add query detecting validators that use badly anchored regular expressions on library/remote input
2023-02-13 11:26:05 +01:00
Kasper Svendsen
74472d786c QLDocs: Document inline_late pragma 2023-02-13 10:51:48 +01:00
erik-krogh
634087b417 Merge branch 'main' into rbPoly 2023-02-13 10:46:00 +01:00
Michael Nebel
2ce6d5f920 Java: Update negative models test to not produce a negative summary for interface member. 2023-02-13 10:45:54 +01:00
Rasmus Wriedt Larsen
5235964b07 sync files 2023-02-13 10:44:12 +01:00
Rasmus Wriedt Larsen
b2e79e2948 Python/Ruby/JS Crypto: Add a few algorithms + block modes
I have tried to add a few links to support the claim that these
algorithms are strong/safe. It wasn't always super easy, so in some
cases I have ended up just linking to the documentation of the
`cryptography` Python package.

Co-authored-by: REDMOND\brodes <brodes@microsoft.com>
2023-02-13 10:40:47 +01:00
Paolo Tranquilli
f07c598a22 Merge pull request #12164 from github/redsun82/swift-codegen-outside-bazel
Swift: make `codegen` run also outside `bazel`
2023-02-13 10:32:20 +01:00
Michael Nebel
80628596dd Java: Exclude interface members from model generation. 2023-02-13 10:21:32 +01:00
Geoffrey White
124e4ddd4f Merge pull request #12150 from geoffw0/cfg2
Swift: control flow for #available
2023-02-13 09:17:06 +00:00
Tom Hvitved
0b8173e2e7 Ruby: Add another data flow test 2023-02-13 09:50:50 +01:00
Paolo Tranquilli
55aacd6fe9 Merge pull request #12137 from github/redsun82/swift-doc-for-schema-doc
Swift: add documentation for generated documentation
2023-02-13 09:43:34 +01:00
Paolo Tranquilli
483a87abe9 Swift: make codegen run also outside bazel 2023-02-13 09:39:31 +01:00
Tony Torralba
4fad01a739 Further refactoring
Avoid having two taint tracking configurations in the same file
2023-02-13 09:18:05 +01:00
Tony Torralba
f3e0b6e62c PathGraph shouldn't be imported in a QLL library 2023-02-13 09:18:05 +01:00
Tony Torralba
422eb0d1bb Add change note 2023-02-13 09:18:05 +01:00
Tony Torralba
5555b5cd19 Add local version of the XXE query 2023-02-13 09:18:05 +01:00
Paolo Tranquilli
542c9218de Merge branch 'main' into redsun82/swift-doc-for-schema-doc 2023-02-13 09:07:02 +01:00
Tom Hvitved
f7a5a33474 Address review comment 2023-02-13 09:01:15 +01:00
erik-krogh
91393a7bc8 add change-note 2023-02-12 23:28:01 +01:00
erik-krogh
6474cfd4c8 add support for express-ws 2023-02-12 23:25:27 +01:00
Jami Cogswell
ad8849c6b8 Java: fix typo 2023-02-12 16:33:26 -05:00
Jami Cogswell
676e4e8461 Java: add change note 2023-02-12 16:32:31 -05:00
Jami Cogswell
ce1c814daa Java: update path-injection query to use new 'read-file' sink kind 2023-02-11 17:10:58 -05:00
Jami Cogswell
c87c3e30c7 Java: update getInvalidModelKind with 'read-file' kind 2023-02-11 17:07:25 -05:00
Owen Mansel-Chan
685b8b4abd Tests are no longer fooled by type aliases 2023-02-10 22:09:21 +00:00
Owen Mansel-Chan
7042f67375 Refactor code to be simpler 2023-02-10 22:09:20 +00:00
Owen Mansel-Chan
778826b528 Accept test changes
Note that
go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected and
go/ql/test/library-tests/semmle/go/Types/Types.expected gain two lines.
In both cases this is because GenericArray and GenericSignature are
each instantiated twice, so they appear with two different locations.
2023-02-10 22:09:20 +00:00
Owen Mansel-Chan
202c0be303 Add hasLocationInfo for Types
It returns a dummy location except for named types with a type
declaration in the source.
2023-02-10 22:09:20 +00:00
Arthur Baars
679f02c274 Address comments 2023-02-10 18:08:30 +01:00
Geoffrey White
8624098318 Swift: sync identical files. 2023-02-10 15:24:57 +00:00
Nora
d55e9d5dac Merge pull request #12000 from github/nora/update-query-history-actions
Rename Query History Actions
2023-02-10 16:18:36 +01:00
Geoffrey White
eda331ebc2 Swift: Clean up. 2023-02-10 15:11:31 +00:00
Geoffrey White
11f022c69f Swift: Add some more qldoc. 2023-02-10 15:02:05 +00:00
Geoffrey White
15b8aa1979 Swift: Effect on other tests :) 2023-02-10 14:16:48 +00:00
Geoffrey White
6cb9198ee2 Swift: Control flow through #available. 2023-02-10 13:32:33 +00:00
Paolo Tranquilli
9d433eb420 Merge branch 'main' into redsun82/swift-doc-for-schema-doc 2023-02-10 14:27:56 +01:00
Michael Nebel
db41463d72 C#: Test of relaxed shift operator requirements. 2023-02-10 10:33:20 +01:00
Geoffrey White
38f4f65fc0 Swift: Add CFG test cases for #available. 2023-02-10 09:29:08 +00:00
Michael Nebel
1bd223b8c8 Merge pull request #12103 from michaelnebel/csharp/scopedmodfier
C# 11: Scoped parameters and local variables.
2023-02-10 10:04:09 +01:00
Paolo Tranquilli
fc7c72db77 Swift: tweaks to the schema doc documentation 2023-02-10 08:58:07 +01:00
Paolo Tranquilli
adf47b9a9c Merge branch 'main' into redsun82/swift-doc-for-schema-doc 2023-02-10 08:49:31 +01:00
Paolo Tranquilli
c92fd97783 Merge pull request #12140 from github/redsun82/swift-fix-upgrade
Swift: remove query predicates in upgrade/downgrade scripts
2023-02-10 08:49:08 +01:00
Geoffrey White
224bc9381a Swift: Fix ConditionElement.toString(). 2023-02-09 21:15:36 +00:00
Michael Nebel
8d8ebeade1 Merge pull request #12067 from michaelnebel/csharp/reflectionload
C#: Delete dead assembly load code.
2023-02-09 18:49:36 +01:00
Paolo Tranquilli
7fa85b34ea Swift: remove query predicates in upgrade/downgrade scripts 2023-02-09 17:24:27 +01:00
Anders Schack-Mulligen
770f3c24bb Java: Improve performance of GeneratedFileMarker. 2023-02-09 15:08:32 +01:00
Ian Lynagh
968f588893 Merge pull request #12090 from igfoo/igfoo/kotlin-1.8.10
Kotlin: 1.8.10 and 1.8.20 are supported, and use 1.8.10 for CI
2023-02-09 12:06:42 +00:00
Paolo Tranquilli
1e279125dc Swift: add documentation for generated documentation 2023-02-09 12:52:16 +01:00
Michael Nebel
0f469ee0f7 C#: Add stats for the scoped annotation relation. 2023-02-09 12:28:15 +01:00
Arthur Baars
07947e6528 Address comments 2023-02-09 12:02:14 +01:00
dependabot[bot]
80a397b4a5 Merge pull request #12134 from github/dependabot/cargo/ruby/serde_json-1.0.93 2023-02-09 10:50:27 +00:00
Michael Nebel
d4985a99e0 C#: Add change note. 2023-02-09 11:32:09 +01:00
Michael Nebel
59ab353827 C#: Add upgrade and downgrade scripts. 2023-02-09 11:32:09 +01:00
Michael Nebel
54b45134ef C#: Add example code including tests. 2023-02-09 11:32:09 +01:00
Michael Nebel
c00b089aa8 C#: Introduce library support for scoped. 2023-02-09 11:32:08 +01:00
Michael Nebel
955f23d021 C#: Introduce extractor support for scoped variables and parameters. 2023-02-09 11:32:08 +01:00
Michael Nebel
dd6ceb7053 C#: Extend the DB schema with a scoped annotation relation. 2023-02-09 11:32:08 +01:00
Michael Nebel
7e174dce8b C#: Re-factor. Introduce variablekind enum. 2023-02-09 11:32:08 +01:00
Michael Nebel
89bebe9d36 C#: Re-factor local variable populate. 2023-02-09 11:32:08 +01:00
Michael B. Gale
ad4ae1c331 Merge pull request #12132 from github/mbg/fix/log-injection-precision
Go: Downgrade `go/log-injection` precision to medium
2023-02-09 10:29:24 +00:00
Michael B. Gale
70a6ff84af Add change note 2023-02-09 09:56:36 +00:00
Geoffrey White
0f6b05dedf Merge pull request #12126 from geoffw0/append
Swift: Move some models into collections
2023-02-09 09:33:08 +00:00
Michael Nebel
b895065be9 Merge pull request #12058 from michaelnebel/csharp/structdefaults
C# 11: Check that we get AST for structs that doesn't initialise all fields.
2023-02-09 09:51:00 +01:00
Anders Schack-Mulligen
3e2bf23bfe Merge pull request #12118 from michaelnebel/telemetry/performancefix
C#/Java: Materialize sink/source/summary predicates to avoid bad join order.
2023-02-09 09:39:38 +01:00
dependabot[bot]
bd98ae0dcc build(deps): bump serde_json from 1.0.91 to 1.0.93 in /ruby
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.91 to 1.0.93.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.91...v1.0.93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-09 08:13:18 +00:00
Erik Krogh Kristensen
f2904ca29b Merge pull request #12135 from github/dependabot/cargo/ql/serde_json-1.0.93
build(deps): bump serde_json from 1.0.92 to 1.0.93 in /ql
2023-02-09 09:08:45 +01:00
dependabot[bot]
5e2f9e1568 build(deps): bump serde_json from 1.0.92 to 1.0.93 in /ql
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.92 to 1.0.93.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.92...v1.0.93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-09 03:09:08 +00:00
Chris Smowton
f113eaa77d Merge pull request #12059 from pwntester/go_twirp_support
[GoLang] Add support for Twirp framework
2023-02-08 21:55:56 +00:00
Michael B. Gale
46d49cd66f Downgrade log injection precision to medium
This is in line with the precision of this query for other languages
2023-02-08 15:49:06 +00:00
Michael Nebel
f6a02310d3 C#: Fix bad join order in TestLibrary characteristic predicate. 2023-02-08 16:37:49 +01:00
Owen Mansel-Chan
18335854b6 Update go/ql/lib/semmle/go/frameworks/Twirp.qll
Co-authored-by: Michael B. Gale <mbg@github.com>
2023-02-08 15:33:35 +00:00
Erik Krogh Kristensen
3ebac65167 apply change-note suggestions from doc review
Co-authored-by: Sam Browning <106113886+sabrowning1@users.noreply.github.com>
2023-02-08 14:55:54 +01:00
Robert
13c7c8449c Merge pull request #12123 from github/robertbrignull/telemetry_privacy_docs
Update telemetry privacy document for UI interaction and exceptions
2023-02-08 13:40:35 +00:00
Arthur Baars
78ad9d67b4 Address comments 2023-02-08 13:40:46 +01:00
Ian Lynagh
844e372651 Kotlin: Add a changenote for 1.8.20 support 2023-02-08 11:35:23 +00:00
Ian Lynagh
069c9674d1 Kotlin: Update supported versions 2023-02-08 11:35:23 +00:00
Ian Lynagh
6255298876 Kotlin: Use 1.8.10 for CI
I don't think there's any need for the CI version to be one of the
versions we build extractors for, so I've removed that check.
2023-02-08 11:35:23 +00:00
Chris Smowton
99bed0b089 Merge pull request #12127 from smowton/smowton/perf/golang-less-string-construction
Go: Consolidate repeated calls to `matches` and `regexpMatch`
2023-02-08 11:07:39 +00:00
Michael Nebel
02364d072e Java: Fix bad join in TestLibrary characteristic predicate. 2023-02-08 11:59:59 +01:00
Alvaro Muñoz
764155ce97 remove bracket 2023-02-08 11:57:03 +01:00
Michael B. Gale
3abf321071 Merge pull request #11496 from github/mbg/add/writable-file-closed-error-query
Go: Add query to detect lack of error handling for `os.File.Close` on writable handles
2023-02-08 10:53:44 +00:00
Owen Mansel-Chan
931c683146 Use regex for case-insensitive string comparisons
This is slightly more efficient.
2023-02-08 10:45:07 +00:00
erik-krogh
eb564760be improve qhelp based on doc review 2023-02-08 11:00:54 +01:00
Mathias Vorreiter Pedersen
7f09684577 Merge pull request #12121 from github/alexdenisov/extract-availability-info
Swift: extract availability info
2023-02-08 09:54:42 +00:00
Michael Nebel
f8dbbe006e C#/Java: Materialize sink/source/summary predicates to avoid join on input/output before filtering. 2023-02-08 10:04:43 +01:00
Owen Mansel-Chan
c427f8fc95 Do not import file defining a Configuration 2023-02-08 06:31:25 +00:00
Henry Mercer
6e9484970f Merge pull request #12128 from github/codeql-ci/atm/release-0.4.7
JS: Bump version numbers of ML-powered packs after 0.4.7 release
2023-02-07 22:29:20 +00:00
Henry Mercer
e972cb069e Merge branch 'main' into codeql-ci/atm/release-0.4.7 2023-02-07 21:31:08 +00:00
github-actions[bot]
4f76ebbb0b JS: Bump version of ML-powered library and query packs to 0.4.8 2023-02-07 19:44:25 +00:00
github-actions[bot]
30b2644f17 JS: Bump patch version of ML-powered library and query packs 2023-02-07 19:34:58 +00:00
Chris Smowton
99d3f689dc Consolidate repeated calls to matches and regexpMatch
This is especially useful if it avoids temporary string construction, such as toLowerCase().matches(...)
2023-02-07 19:22:49 +00:00
Robert
15b293c56d Apply copy edits 2023-02-07 17:11:47 +00:00
Geoffrey White
60e7d6b540 Swift: Move insert to RangeReplaceableCollection. 2023-02-07 17:08:23 +00:00
Geoffrey White
7cb665cde1 Swift: Move popLast to BidirectionalCollection and add popFirst. 2023-02-07 16:56:00 +00:00
Geoffrey White
d17c7bb0e8 Swift: Move first(_:), last(_:) into Sequence, BidirectionalCollection. 2023-02-07 16:47:02 +00:00
Geoffrey White
3586926157 Swift: Move first, last into Collection, BidirectionalCollection. 2023-02-07 16:36:06 +00:00
Taus
080ce09bd7 Python: Update six test expectations 2023-02-07 16:21:15 +00:00
Taus
8dea993f41 Python: Update failing test
Seems the name for the codec changed between Python 2 and 3. :)
2023-02-07 16:21:15 +00:00
Taus
49a3dd6131 Python: Clean up version handling
Depends on an internal PR.
2023-02-07 16:21:15 +00:00
Mathias Vorreiter Pedersen
334c41c3e1 Merge pull request #12122 from github/post-release-prep/codeql-cli-2.12.2
Post-release preparation for codeql-cli-2.12.2
2023-02-07 16:17:57 +00:00
Geoffrey White
b69d8625e5 Swift: Move append methods into RangeReplaceableCollection. 2023-02-07 16:07:35 +00:00
Geoffrey White
f9f08fff83 Swift: Use RangeReplaceableCollection in the test. 2023-02-07 16:03:51 +00:00
Tom Hvitved
8e8897b08b Data flow: Sync files 2023-02-07 15:15:04 +01:00
Tom Hvitved
10534b62c9 Data flow: Call context virtual dispatch pruning in stage 1 2023-02-07 15:14:27 +01:00
Robert
80a503b65d Update telemetry privacy document for UI interaction and exceptions 2023-02-07 14:00:22 +00:00
Mathias Vorreiter Pedersen
1980e25ac9 Merge pull request #12120 from MathiasVP/even-fewer-strings
C++: Avoid unnecessary calls to `toLowerCase()`
2023-02-07 13:57:12 +00:00
Alex Denisov
3448cde048 Swift: add database migration 2023-02-07 14:31:19 +01:00
Alex Denisov
712c25e6f4 Swift: extract availability info 2023-02-07 14:26:39 +01:00
github-actions[bot]
522a892d32 Post-release preparation for codeql-cli-2.12.2 2023-02-07 13:19:06 +00:00
Mathias Vorreiter Pedersen
746f04bafc C++: Construct fewer strings. 2023-02-07 11:44:32 +00:00
Tom Hvitved
984729f9b0 Merge pull request #12117 from hvitved/ruby/delay-location-to-string
Ruby: Avoid computing `Location::toString` in full
2023-02-07 12:42:03 +01:00
Mathias Vorreiter Pedersen
ff29356ae9 Merge pull request #12106 from MathiasVP/fewer-strings
C++: Replace `toUpperCase().matches("...")` with case-insensitive `regexpMatch`
2023-02-07 11:31:36 +00:00
Paolo Tranquilli
c9397a5abf Merge pull request #10950 from github/redsun82/swift-regex
Swift: extract `RegexLiteralExpr`
2023-02-07 11:30:43 +01:00
Geoffrey White
d8616e77d5 Merge pull request #12108 from geoffw0/strings3
Swift: Remove a no-longer-needed special case from swift/unsafe-js-eval.
2023-02-07 09:44:41 +00:00
Mathias Vorreiter Pedersen
aef66c462a Merge pull request #12107 from aibaars/downgrade-tree-sitter
Ruby: downgrade tree-sitter to 0.20.7
2023-02-07 09:29:42 +00:00
Paolo Tranquilli
a3b443c310 Swift: add upgrade/downgrade scripts for regex extraction 2023-02-07 10:21:37 +01:00
Paolo Tranquilli
ad04a408c7 Swift: add doc to RegexLiteralExpression 2023-02-07 10:21:37 +01:00
Paolo Tranquilli
50889b8fa1 Swift: move regex test to integration tests 2023-02-07 10:21:37 +01:00
Tom Hvitved
c0e3186607 Ruby: Avoid computing Location::toString in full 2023-02-07 10:06:47 +01:00
Paolo Tranquilli
d201c1eadd Swift: support linux-only tests 2023-02-07 09:41:06 +01:00
Paolo Tranquilli
a244b825df Merge branch 'main' into redsun82/swift-regex 2023-02-07 09:37:09 +01:00
Anders Schack-Mulligen
3c580896dc Merge pull request #11712 from aschackmull/java/constant-guards
Java: Apply deadcode guard to data flow nodes.
2023-02-07 09:14:20 +01:00
Harry Maclean
43ce26e4d0 Ruby: re-add Eval.rb 2023-02-07 09:37:26 +13:00
Jeroen Ketema
a4c3ea2efc Merge pull request #9245 from ihsinme/ihsinme-patch-102
CPP: Add query for CWE-805: Buffer Access with Incorrect Length Value using some functions
2023-02-06 21:24:07 +01:00
Jeroen Ketema
1c35109675 C++: Add experimental tag to experimental query 2023-02-06 20:31:26 +01:00
Jeroen Ketema
868f07bc91 Merge branch 'main' into ihsinme-patch-102 2023-02-06 20:16:53 +01:00
Geoffrey White
996536b08e Swift: Remove a no-longer-needed special case from swift/unsafe-js-eval. 2023-02-06 17:35:21 +00:00
Mathias Vorreiter Pedersen
4016299aa8 Update cpp/ql/lib/semmle/code/cpp/security/Encryption.qll
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2023-02-06 15:55:15 +00:00
Arthur Baars
12f5732782 Ruby: downgrade tree-sitter to 0.20.7
The 0.20.9 version caused a stack overflow error on
the mongo-ruby-driver repository.
2023-02-06 16:27:51 +01:00
Erik Krogh Kristensen
4eebeab8a8 Merge pull request #12078 from erik-krogh/qlCache
QL: simplify the QL-for-QL workflow, which should also fix the cache
2023-02-06 16:21:45 +01:00
Mathias Vorreiter Pedersen
1c9a526afa C++: Construct fewer strings. 2023-02-06 15:18:15 +00:00
erik-krogh
9364a85e49 add Rust format check to QL-for-QL tests 2023-02-06 14:26:30 +01:00
Erik Krogh Kristensen
9360ae9638 Merge pull request #12076 from erik-krogh/poly-sink-track
PY: add tracking of strings to compile-sites for poly-redos
2023-02-06 14:21:04 +01:00
Anders Schack-Mulligen
b4607d3fab Java: Add change notes. 2023-02-06 13:55:34 +01:00
Geoffrey White
dc59ed08f9 Merge pull request #12094 from geoffw0/string2
Swift: Models for the String class
2023-02-06 11:24:19 +00:00
Chris Smowton
cd2fc6566f Merge pull request #12101 from owen-mc/go/gofmt-remove-confusing-error-message
Fix files that gofmt can't parse
2023-02-06 10:58:54 +00:00
Mathias Vorreiter Pedersen
00fe448e3a Merge pull request #12072 from aschackmull/dataflow/stage3-perf
Dataflow: Fix join in `fwdFlowRead` (take 2)
2023-02-06 10:43:11 +00:00
Erik Krogh Kristensen
f32fa25c1a Merge pull request #12100 from github/dependabot/cargo/ql/serde_json-1.0.92
build(deps): bump serde_json from 1.0.91 to 1.0.92 in /ql
2023-02-06 10:33:32 +01:00
Arthur Baars
e382d6d000 Ruby: update stats 2023-02-06 10:28:19 +01:00
Arthur Baars
ec46f33a01 Ruby: add change note 2023-02-06 10:17:19 +01:00
Arthur Baars
f391948b53 Ruby: update expected output 2023-02-06 10:17:19 +01:00
Arthur Baars
4af0c4bb03 Ruby: desugar one-line pattern matches 2023-02-06 10:17:19 +01:00
Arthur Baars
3c15fd266d Ruby: add one-line pattern match test 2023-02-06 10:17:19 +01:00
Arthur Baars
edbba85b96 Ruby: add one-line pattern matches to AST 2023-02-06 10:17:18 +01:00
Arthur Baars
e390ca50b0 Ruby: upgrade/downgrade scripts 2023-02-06 10:17:18 +01:00
Arthur Baars
90c51ef404 Ruby: re-generate dbscheme and library 2023-02-06 10:17:18 +01:00
Arthur Baars
c554a10e06 Ruby: update tree-sitter-ruby 2023-02-06 10:17:18 +01:00
Michael B. Gale
f7a2a8677a Rename change note file 2023-02-06 09:13:11 +00:00
Michael B. Gale
6c0d2bdee1 Add example without defer statement 2023-02-06 09:10:41 +00:00
Michael B. Gale
25f907867b Update expected test output 2023-02-06 08:51:46 +00:00
Michael B. Gale
abe38373da Inline precededBySync 2023-02-06 08:47:47 +00:00
Michael B. Gale
c252ec0414 Add test for deferred close that returns error 2023-02-06 08:47:47 +00:00
Michael B. Gale
e05bce9863 Update expected test results 2023-02-06 08:47:46 +00:00
Michael B. Gale
314ecab90a Use dominatesNode and improve variable naming 2023-02-06 08:47:46 +00:00
Michael B. Gale
85a339030b Make the query a path-problem 2023-02-06 08:47:46 +00:00
Michael B. Gale
199c8641ec Rename close to sink in query 2023-02-06 08:47:46 +00:00
Michael B. Gale
f648b021a9 Despecialise parameter names for precededBySync 2023-02-06 08:47:46 +00:00
Michael B. Gale
bd6c167be6 Fixup: more docs improvements 2023-02-06 08:47:46 +00:00
Michael B. Gale
f866e16679 Use any instead of exists for isCloseSink 2023-02-06 08:47:45 +00:00
Michael B. Gale
5ab6056b26 Fixup: docs comment 2023-02-06 08:47:45 +00:00
Michael B. Gale
3f446bc76e Use three-argument hasQualifiedName 2023-02-06 08:47:45 +00:00
Michael B. Gale
07041bb659 Use Method instead of Function where able 2023-02-06 08:47:45 +00:00
Michael B. Gale
416ed57583 Fix qldoc comments 2023-02-06 08:47:45 +00:00
Michael B. Gale
f321adf9f4 Fix typo
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2023-02-06 08:47:44 +00:00
Michael B. Gale
10109b4925 Fix class comments 2023-02-06 08:47:44 +00:00
Michael B. Gale
49ce91fd5b Update precision to high 2023-02-06 08:47:44 +00:00
Michael B. Gale
7e9617f3ce Detect lack of error handling for os.File.Close 2023-02-06 08:47:43 +00:00
Tamás Vajk
c03fe70b8d Merge pull request #12086 from tamasvajk/feature/fix-exception-handling-archive
C#: Change handled exception in `TrapWriter.ArchiveContents`
2023-02-06 08:53:56 +01:00
Owen Mansel-Chan
9ed7836367 Fix files that gofmt can't parse
We have some .go files that gofmt can't parse because they don't start
with "package". This was intentional, as they are fragments to be
included in .qhelp files. They don't affect the return code as gofmt
doesn't change their formatting, so this wasn't changing the result of
the check. However, it was confusing that when the check failed because
some other files weren't formatted correctly, the user would see the
stderr complaining about those files, so we capture stderr.

It would be an improvement to print which files are not formatted
correctly, but that was beyond my abilities with bash and makefiles.
2023-02-06 07:16:58 +00:00
dependabot[bot]
33e8414fc4 build(deps): bump serde_json from 1.0.91 to 1.0.92 in /ql
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.91 to 1.0.92.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.91...v1.0.92)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 03:29:59 +00:00
Chris Smowton
03385ac0b5 Merge pull request #12097 from github/smowton/admin/macos-ventura
Add MacOS Ventura to supported platforms
2023-02-04 17:54:21 +00:00
Philip Ginsbach
8cefde36bf Merge pull request #12088 from github/ginsbach/DocumentFinalAlias
document final type aliases
2023-02-04 12:23:03 +00:00
Chris Smowton
f8b574c654 Add MacOS Ventura to supported platforms
Rebase of e8bf8fe7a4
2023-02-04 08:28:03 +00:00
Harry Maclean
02b09ca9f7 Ruby: Remove unused test files 2023-02-04 14:42:59 +13:00
Harry Maclean
cfb3bc9dce Ruby: Remove unused test file 2023-02-04 14:30:56 +13:00
Harry Maclean
0711326619 Ruby: Move PosixSpawn tests to their own directory 2023-02-04 14:30:23 +13:00
Harry Maclean
dbbef0534b Ruby: Move Core tests into core directory 2023-02-04 14:28:25 +13:00
Harry Maclean
b5d98d9011 Ruby: Move GraphQL test to their own directory 2023-02-04 14:25:38 +13:00
Harry Maclean
6c816d5602 Ruby: Move ActionDispatch tests to own directory 2023-02-04 14:19:08 +13:00
Harry Maclean
58d7af4018 Ruby: Move ActionView tests into their own dir
This ensures that changes to unrelated test files don't affect these
tests.
2023-02-04 14:19:08 +13:00
Mathias Vorreiter Pedersen
7642245747 Merge pull request #12095 from github/post-release-prep/codeql-cli-2.12.2
Post-release preparation for codeql-cli-2.12.2
2023-02-04 01:03:14 +00:00
Jami Cogswell
2d7e71dfce Java: add read-file sink kind for first arg of copy 2023-02-03 17:28:46 -05:00
github-actions[bot]
57f40ccd48 Post-release preparation for codeql-cli-2.12.2 2023-02-03 21:12:22 +00:00
Alvaro Muñoz
23c7bc8143 import RequestForgery from tests.ql 2023-02-03 22:05:50 +01:00
Jami
b6805c6913 Merge pull request #11863 from jcogs33/jcogs33/update-paramsString
Java: update paramsString
2023-02-03 15:47:38 -05:00
Sarita Iyer
8edd378290 Merge pull request #12077 from github/codeql-cli-articles-migration-update
Update CodeQL CLI docs articles and links to point to new location on GitHub Docs site
2023-02-03 15:25:33 -05:00
Geoffrey White
364c173fc3 Swift: Accept additional taint flow in UnsafeJsEval test. 2023-02-03 19:21:10 +00:00
Geoffrey White
1f69fff26c Swift: Fix mistake caught by QL-for-QL. 2023-02-03 19:15:08 +00:00
Geoffrey White
f82a548cf9 Swift: Comments and formatting. 2023-02-03 18:50:51 +00:00
Geoffrey White
c666f9c845 Merge pull request #12089 from geoffw0/filedoc
Swift: QLDoc models files consistently.
2023-02-03 18:45:20 +00:00
Geoffrey White
ec72c7504c Swift: Add a partial model of Collection. 2023-02-03 18:42:42 +00:00
Geoffrey White
e357b44943 Swift: Add a partial model of Sequence. 2023-02-03 18:42:42 +00:00
Geoffrey White
4bb0bbf488 Swift: Remove redundant copies. 2023-02-03 18:42:41 +00:00
Geoffrey White
e230951a14 Swift: Model StringProtocol methods. 2023-02-03 18:42:41 +00:00
Sarita Iyer
75b0676c95 Add tocs with links to deprecated articles 2023-02-03 13:37:53 -05:00
Jonas Jensen
41f7c7ae53 Merge pull request #12092 from jbj/aliases-upper-case 2023-02-03 18:40:53 +01:00
Alvaro Muñoz
04d5b7e579 make RequestForgery import private 2023-02-03 18:19:35 +01:00
Alvaro Muñoz
4b198f9af8 apply code review feedback 2023-02-03 18:12:49 +01:00
Alvaro Muñoz
844193d065 use regexp to capture generated file names 2023-02-03 18:08:56 +01:00
Alvaro Muñoz
1d0e80c2f5 Apply suggestions from code review
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2023-02-03 17:59:29 +01:00
Alvaro Muñoz
3002230af9 remove duplicated import 2023-02-03 17:48:13 +01:00
Philip Ginsbach
1ec2c2591b fix documentation generator problem 2023-02-03 16:42:07 +00:00
Owen Mansel-Chan
2f637e2c8e Remove unused variable 2023-02-03 16:36:20 +00:00
Alvaro Muñoz
c517eb89b2 add more sinks 2023-02-03 17:33:08 +01:00
Jonas Jensen
73112e401c Change type name to upper case
QL doesn't allow types to be declared in lower case, so the example did
not compile.
2023-02-03 17:30:12 +01:00
Philip Ginsbach
a354e776bf document final type aliases 2023-02-03 15:59:47 +00:00
Alvaro Muñoz
20dc30d7e8 add RequestForgery test 2023-02-03 16:38:56 +01:00
Philip Ginsbach
a639f13fd9 Merge pull request #12085 from github/ginsbach/DocumentModuleSignatureMemberDefaults
document module signature member defaults
2023-02-03 15:33:00 +00:00
Alvaro Muñoz
6b3d458865 Apply suggestions from code review
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2023-02-03 16:20:21 +01:00
Alvaro Muñoz
c7637a7e1f Apply suggestions from code review
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2023-02-03 16:19:48 +01:00
Anders Schack-Mulligen
2d6d8aaa74 Java: Account for additional constants in ArrayIndexOutOfBounds query. 2023-02-03 16:16:39 +01:00
Anders Schack-Mulligen
a1aeb995e6 Java: Apply deadcode guard to data flow nodes. 2023-02-03 16:16:39 +01:00
Anders Schack-Mulligen
e8dbd65d77 Java: Refactor compile-time constant calculation and apply to ConstantIntegerExpr. 2023-02-03 16:16:27 +01:00
Alvaro Muñoz
a0cf8e786c fix SSRF sink 2023-02-03 16:16:00 +01:00
Alvaro Muñoz
7140b956e8 improve generated files matching predicates 2023-02-03 16:13:44 +01:00
Sarita Iyer
d99f7b56bd Merge branch 'codeql-cli-articles-migration-update' of https://github.com/github/codeql into codeql-cli-articles-migration-update 2023-02-03 09:56:51 -05:00
Sarita Iyer
c33c5ed517 Update codeql-cli links 2023-02-03 09:56:49 -05:00
Tamas Vajk
f90c5346bf C#: Change handled exception in TrapWriter.ArchiveContents 2023-02-03 15:13:23 +01:00
Geoffrey White
38eeb9c747 Swift: Model String methods. 2023-02-03 12:26:55 +00:00
Geoffrey White
1077dcd2e3 Swift: Model String initializers. 2023-02-03 11:36:35 +00:00
Philip Ginsbach
b8bd98e476 Merge pull request #12075 from github/ginsbach/RemoveIncorrectStatement
remove statement about namespaces from documentation that no longer holds
2023-02-03 11:18:07 +00:00
Geoffrey White
142ca0c9fb Swift: Model StringProtocol initializers. 2023-02-03 10:53:44 +00:00
Geoffrey White
d888510688 Swift: Fix incorrect taint to String fields. 2023-02-03 10:21:52 +00:00
Geoffrey White
d25de8c764 Swift: Taint fields of StringProtocol. 2023-02-03 10:16:33 +00:00
Philip Ginsbach
e552a6206d shadowing and visibility of default predicates 2023-02-03 10:11:25 +00:00
Geoffrey White
21abe54d8d Swift: Greatly extend tests of taint through strings. 2023-02-03 10:11:12 +00:00
Philip Ginsbach
09fdf744d4 introduce module signature member defaults 2023-02-03 10:01:59 +00:00
Geoffrey White
bf6ef43451 Swift: Document library model files consistently. 2023-02-03 09:59:35 +00:00
erik-krogh
3545bb0819 adjust qhelp based on review 2023-02-03 10:50:18 +01:00
Mathias Vorreiter Pedersen
4e7ca1a175 Merge pull request #12082 from github/post-release-prep/codeql-cli-2.12.2
Post-release preparation for codeql-cli-2.12.2
2023-02-03 09:40:57 +00:00
Philip Ginsbach
808d3e3a1f Merge pull request #12084 from github/ginsbach/IncorrectEnvironmentNumbering
we actually only distinguish four environments
2023-02-03 09:37:39 +00:00
Alvaro Muñoz
50bd0707ce remove redundant import 2023-02-03 10:19:35 +01:00
Philip Ginsbach
56e0b19df8 we actually only distinguish four environments 2023-02-03 09:04:43 +00:00
Alvaro Muñoz
8cb022713e include review feedback 2023-02-03 10:01:55 +01:00
Arthur Baars
9a4cec7691 Merge pull request #11956 from aibaars/json-log
Ruby: structured logging
2023-02-03 09:54:49 +01:00
Alvaro Muñoz
13242df149 Apply suggestions from code review
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2023-02-03 09:45:00 +01:00
github-actions[bot]
faf21f3edb Post-release preparation for codeql-cli-2.12.2 2023-02-02 23:01:04 +00:00
erik-krogh
6e712b293a add tracking of strings to compile-sites for poly-redos, in the style of Ruby 2023-02-02 22:56:20 +01:00
Jami Cogswell
30b1a2edbc Java: add first argument to copy sink 2023-02-02 16:20:54 -05:00
Jami Cogswell
61a8f5e425 Java: add signature to createTempDirectory sink 2023-02-02 16:19:20 -05:00
erik-krogh
34266cfa4c simplify the QL-for-QL workflow, which should also fix the cache 2023-02-02 22:17:38 +01:00
Sarita Iyer
fd977cc277 Update CONTRIBUTING.md 2023-02-02 16:13:13 -05:00
Sarita Iyer
465a3e0ece fix typo 2023-02-02 15:36:34 -05:00
Sarita Iyer
9943d0c054 update anchor links 2023-02-02 15:26:53 -05:00
Sarita Iyer
9b17ee9326 add back hidden toc tree 2023-02-02 14:39:49 -05:00
Sarita Iyer
0ab982891e adding back toc-trees to fix error 2023-02-02 14:31:03 -05:00
Sarita Iyer
2772cf79f4 Update CodeQL CLI articles with migration message 2023-02-02 14:11:02 -05:00
erik-krogh
52959d7c0a add failing test for not tracking strings to re.compile 2023-02-02 19:10:32 +01:00
Erik Krogh Kristensen
c8cfb6a0cc Merge pull request #12065 from knewbury01/knewbury01/fix-js-cleartext-logging-doc
Update JS CleartextLogging qhelp
2023-02-02 18:23:59 +01:00
Philip Ginsbach
55cd436b06 Merge pull request #12074 from github/ginsbach/DocumentShadowing2
shadowing in the QL language specification
2023-02-02 17:13:47 +00:00
Philip Ginsbach
1542353af7 statement no longer holds for namespaces with shadowing 2023-02-02 16:55:06 +00:00
Alvaro Muñoz
2576a09af9 remove unnecessary line 2023-02-02 17:50:50 +01:00
Nora Dimitrijević
a3a01ddc11 Merge pull request #11855 from d10c/swift/extract-captures 2023-02-02 17:50:41 +01:00
Mathias Vorreiter Pedersen
cd660e1067 Merge pull request #12071 from github/release-prep/2.12.2
Release preparation for version 2.12.2
2023-02-02 16:49:44 +00:00
Philip Ginsbach
ab184ebd78 shadowing in the QL language specification 2023-02-02 16:19:18 +00:00
Kristen Newbury
21b4931fbb Merge branch 'main' into knewbury01/fix-js-cleartext-logging-doc 2023-02-02 11:12:57 -05:00
Kristen Newbury
231110ddca Update javascript/ql/src/Security/CWE-312/CleartextLogging.qhelp
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2023-02-02 11:12:44 -05:00
Henry Mercer
65863f1fc7 Merge pull request #10826 from github/dependabot/github_actions/actions/setup-dotnet-3.0.2
build(deps): bump actions/setup-dotnet from 2 to 3
2023-02-02 15:54:55 +00:00
Philip Ginsbach
1472d4b782 Merge pull request #12062 from github/ginsbach/DocumentShadowing
shadowing in the handbook
2023-02-02 15:52:54 +00:00
Anders Schack-Mulligen
67d4ed53b9 Dataflow: Sync. 2023-02-02 16:33:00 +01:00
Anders Schack-Mulligen
8cb233df1a Dataflow: A proper perf fix for the stage-dependent fanout direction of the Content-to-Ap relation. 2023-02-02 16:31:07 +01:00
Jeroen Ketema
3cf5107b45 Apply suggestions from code review 2023-02-02 15:48:29 +01:00
github-actions[bot]
a4fa984792 Release preparation for version 2.12.2 2023-02-02 14:34:55 +00:00
Michael Nebel
77283be6c0 Merge pull request #12068 from michaelnebel/csharp/dotnetpublishtest
C#: Avoid that the dotnet publish test refers to a specific .NET vers…
2023-02-02 15:34:06 +01:00
Michael Nebel
960f776e29 C#: Avoid that the dotnet publish test refers to a specific .NET version. 2023-02-02 14:18:50 +01:00
Philip Ginsbach
4282e1a18e explicitly mention aliases 2023-02-02 13:04:43 +00:00
Philip Ginsbach
2b719d503d visible namespaces also include private imports 2023-02-02 13:03:30 +00:00
Michael Nebel
ae10a6beb0 C#: Check that we get AST for struct that doesn't initialize all fields. 2023-02-02 12:50:59 +01:00
Michael Nebel
3cd2024a66 Merge pull request #12060 from michaelnebel/csharp11/nameof
C# 11: Nameof on attribute declarations.
2023-02-02 12:46:28 +01:00
Nora Dimitrijević
ad5dbe18a4 Swift: db upgrade/downgrade script 2023-02-02 12:00:47 +01:00
Nora Dimitrijević
50e5b29eb7 Swift: all Callables can have captures [codegen'd] 2023-02-02 11:56:51 +01:00
Nora Dimitrijević
ce2e7f1d12 Swift: all Callables can have captures [hand-written] 2023-02-02 11:35:50 +01:00
Nora Dimitrijević
d230431006 Swift: extract closure captures (codegen'd part) 2023-02-02 11:35:49 +01:00
Nora Dimitrijević
6895c113cf Swift: extract closure captures (hand-written part) 2023-02-02 11:30:33 +01:00
Nora Dimitrijević
87f7bc3a63 Swift: introduce closure capture AST test 2023-02-02 11:30:33 +01:00
Michael Nebel
470e4b64ea C#: Delete assembly load code as it always throws a PlatformNotSupported exception. 2023-02-02 10:06:04 +01:00
Tony Torralba
62158c5e49 Merge pull request #12044 from atorralba/atorralba/webview-models
Swift: Add new source and flow step related to WkWebView
2023-02-02 09:27:21 +01:00
Michael Nebel
4089845ea4 C#: Test that nameof can used on method parameters and type parameters in attribute declarations. 2023-02-02 09:25:24 +01:00
dependabot[bot]
787fe38d90 build(deps): bump actions/setup-dotnet from 2 to 3.0.2
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 2 to 3.0.2.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v2...v3.0.2)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 08:09:43 +00:00
Michael Nebel
7271d9987e Merge pull request #11940 from michaelnebel/csharp/dotnet7
C#: Update project targets, workflows and other scripts to use .NET 7.
2023-02-02 08:14:55 +01:00
Nora Dimitrijević
e137993acd Merge pull request #12061 from d10c/cpp/missing-check-scanf-join-order-fix 2023-02-02 07:57:21 +01:00
Kristen Newbury
dc5eb40d5f Update JS CleartextLogging qhelp 2023-02-01 16:29:13 -05:00
Harry Maclean
d671cc6e43 Merge pull request #12052 from hmac/barrier-guard-fix 2023-02-02 08:16:07 +13:00
Chuan-kai Lin
255f989ede Merge pull request #12034 from cklin/document-assume-small-delta
Document pragma[assume_small_delta]
2023-02-01 10:36:40 -08:00
Alvaro Muñoz
d6f1dfa205 update tests 2023-02-01 17:58:32 +01:00
Philip Ginsbach
c5deb8544b rework documentation of namespaces to take account of shadowing 2023-02-01 16:56:35 +00:00
Tony Torralba
24527bfc4e Minor change in WKNavigationDelegateSource to work around a bug 2023-02-01 17:44:08 +01:00
Tony Torralba
644bc56568 Add new source and flow step related to WkWebView 2023-02-01 17:44:06 +01:00
Tony Torralba
407e7cbbde Merge pull request #12045 from atorralba/atorralba/more-custom-url-schemes
Swift: Add more sources for custom URL schemes
2023-02-01 17:40:20 +01:00
Joe Farebrother
97b2e852c9 Merge pull request #11713 from joefarebrother/sensitive-result-receiver
Java: Add query for leaking sensitive data through a ResultReceiver
2023-02-01 16:34:17 +00:00
Nora Dimitrijević
1df0be3ca2 C++: Fix join order in cpp/missing-check-scanf
The issues were:
* `revFlow`: `revFlow` joins `fwdFlow` on `vn`.
* `Node.getASuccessor()`: `MkNode` self-join on `vn`.
* `hasFlow/5`: `MkNode` self-join on `vn`.
2023-02-01 16:29:43 +01:00
Tony Torralba
834fc51a3a Update java/ql/src/Security/CWE/CWE-927/SensitiveResultReceiver.ql 2023-02-01 15:26:26 +01:00
Tony Torralba
43b234eeb5 Switch to MaD models for UISceneDelegate methods 2023-02-01 15:15:51 +01:00
Tony Torralba
f7cc5f9627 Add more sources for custom URL schemes
Also add the appropriate steps so that these sources are useful
2023-02-01 15:07:37 +01:00
Alvaro Muñoz
4d6b35f891 apply gofmt 2023-02-01 14:51:48 +01:00
Alvaro Muñoz
70a151af02 add change-notes 2023-02-01 14:49:30 +01:00
Geoffrey White
96ee0f68b0 Merge pull request #11935 from geoffw0/protocol-extension
Swift: Flow sources through protocol extensions
2023-02-01 13:47:09 +00:00
Alvaro Muñoz
a3188f2e10 address review feedback 2023-02-01 14:43:51 +01:00
Alvaro Muñoz
3502ab6523 fix missing QLDocs and refactor ServiceInterface 2023-02-01 14:37:38 +01:00
Alvaro Muñoz
afa6b1cec5 Initial support for Twirp framework 2023-02-01 13:55:09 +01:00
Joe Farebrother
74dba953ca Apply suggestions from docs review
Co-authored-by: Sam Browning <106113886+sabrowning1@users.noreply.github.com>
2023-02-01 12:54:19 +00:00
Erik Krogh Kristensen
bc36a75bde Merge pull request #12057 from erik-krogh/syncPyFlow
PY: Sync a dataflow config
2023-02-01 11:58:40 +01:00
erik-krogh
77e014c5a4 sync added dataflow config 2023-02-01 11:46:57 +01:00
Erik Krogh Kristensen
01f6862965 Merge pull request #11833 from erik-krogh/trackPyReg
PY: track string-constants to regular expression uses
2023-02-01 11:40:42 +01:00
Arthur Baars
a46061541b Ruby: address review comment 2023-02-01 09:59:05 +01:00
Arthur Baars
fa81d9da18 Apply suggestions from code review
Co-authored-by: Harry Maclean <hmac@github.com>
2023-02-01 09:47:39 +01:00
Tony Torralba
837cdf7782 Merge pull request #12046 from atorralba/atorralba/urlrequest-models
Swift: Add taint for URLRequest fields
2023-02-01 09:24:17 +01:00
Geoffrey White
b9d487ac35 Merge branch 'main' into protocol-extension 2023-02-01 08:21:05 +00:00
Erik Krogh Kristensen
16049d694b Merge pull request #12055 from github/dependabot/cargo/ql/tracing-0.1.37
Bump tracing from 0.1.35 to 0.1.37 in /ql
2023-02-01 09:07:11 +01:00
dependabot[bot]
373148decd Bump tracing from 0.1.35 to 0.1.37 in /ql
Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.35 to 0.1.37.
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.35...tracing-0.1.37)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 03:11:28 +00:00
Harry Maclean
da45d3aa7f Ruby: Fix string comparison barrier guard
`strNode` was not properly restricted for some cases.
2023-02-01 14:40:53 +13:00
Harry Maclean
0d68d88741 Merge pull request #11934 from hmac/actioncontroller-filters 2023-02-01 09:10:30 +13:00
Geoffrey White
7f58a2222a Merge branch 'main' into protocol-extension 2023-01-31 16:06:55 +00:00
Chris Smowton
6b0b73b5f6 Merge pull request #12033 from intrigus-lgtm/patch-8
Fix errorneous slash
2023-01-31 14:39:51 +00:00
Mathias Vorreiter Pedersen
a2248e6ca6 Merge pull request #12030 from MathiasVP/iterator-public-models
C++: Make iterator classes public
2023-01-31 14:11:52 +00:00
Mathias Vorreiter Pedersen
0d38ff8e8c Merge pull request #11920 from gsingh93/bit-shift-range
C++: Improve left shift and right shift range analysis accuracy
2023-01-31 14:01:41 +00:00
Erik Krogh Kristensen
8bc9ce749f Merge pull request #12038 from github/dependabot/cargo/ql/tracing-subscriber-0.3.16
Bump tracing-subscriber from 0.3.15 to 0.3.16 in /ql
2023-01-31 14:35:35 +01:00
Arthur Baars
57012714d6 Ruby: serialize timestamps as ISO8601 2023-01-31 14:32:29 +01:00
dependabot[bot]
56a0b1d2d8 Merge pull request #12024 from github/dependabot/cargo/ruby/clap-3.0.14 2023-01-31 13:30:21 +00:00
dependabot[bot]
597c71011e Bump tracing-subscriber from 0.3.15 to 0.3.16 in /ql
Bumps [tracing-subscriber](https://github.com/tokio-rs/tracing) from 0.3.15 to 0.3.16.
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.15...tracing-subscriber-0.3.16)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 13:09:13 +00:00
Erik Krogh Kristensen
683761098d Merge pull request #12041 from github/dependabot/cargo/ql/flate2-1.0.25
Bump flate2 from 1.0.24 to 1.0.25 in /ql
2023-01-31 14:07:09 +01:00
Mathias Vorreiter Pedersen
fcc4c91739 C++: More responding to comments. 2023-01-31 13:01:00 +00:00
dependabot[bot]
7f22c4c474 Bump clap from 3.0.12 to 3.0.14 in /ruby
Bumps [clap](https://github.com/clap-rs/clap) from 3.0.12 to 3.0.14.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v3.0.12...v3.0.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 12:49:34 +00:00
dependabot[bot]
8410e46067 Bump flate2 from 1.0.24 to 1.0.25 in /ql
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.24 to 1.0.25.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.24...1.0.25)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 12:48:10 +00:00
Erik Krogh Kristensen
481dab700c Merge pull request #12037 from github/dependabot/cargo/ql/num_cpus-1.14.0
Bump num_cpus from 1.13.1 to 1.14.0 in /ql
2023-01-31 13:45:43 +01:00
Michael Nebel
478474bbed C#: Add ref field test case. 2023-01-31 13:35:47 +01:00
yoff
7ae389bb28 Merge pull request #12026 from erik-krogh/nodePty
JS: add code-injection sink for node-pty
2023-01-31 13:27:32 +01:00
Michael Nebel
ecadb56419 C#: Update CIL consistency test expected output. 2023-01-31 13:21:00 +01:00
Michael Nebel
5657bd0547 C#: Update type annontations test to exclude OS specific stuff. 2023-01-31 13:21:00 +01:00
Michael Nebel
177fcbb4eb C#: Update attribute test to exclude OS specific declarations. 2023-01-31 13:21:00 +01:00
Michael Nebel
0ed48616a7 C#: Use stubs for CWE-321/HardcodedSymmetricEncryptionKey. 2023-01-31 13:21:00 +01:00
Michael Nebel
9808482c41 C#: Update Minimal stubs from source testcase expected output. 2023-01-31 13:21:00 +01:00
Michael Nebel
3510f465b2 C#: Use stubs for ThreadUnsafeICryptoTransformLambda. 2023-01-31 13:21:00 +01:00
Michael Nebel
f3555b1076 C#: Update options files as some classes has been moved to other dll's. 2023-01-31 13:21:00 +01:00
Michael Nebel
5ccfc4d3f4 C#: Add System.Security.Cryptography as a dependency to the HashWithoutSalt query test. 2023-01-31 13:21:00 +01:00
Michael Nebel
fd74c10b06 C#: Use stubs for ThreadUnsafeICryptoTransform. 2023-01-31 13:21:00 +01:00
Michael Nebel
14888d4382 C#: Use stubs for CWE-327 test cases. 2023-01-31 13:21:00 +01:00
Michael Nebel
89de6cb8a0 C#: Update library tests. 2023-01-31 13:20:59 +01:00
Michael Nebel
33a923a85b C#: Use IsKind instead of Kind (compiler warning). 2023-01-31 13:20:59 +01:00
Michael Nebel
3a4e5700e8 C#: Update project targets, workflows and other scripts to use .NET 7. 2023-01-31 13:20:59 +01:00
Michael Nebel
86e9bf2f81 Merge pull request #11996 from michaelnebel/csharp/refstructreffield
C# 11: Extractor support for `ref` fields in `ref struct`.
2023-01-31 13:08:57 +01:00
dependabot[bot]
423bab54d3 Bump num_cpus from 1.13.1 to 1.14.0 in /ql
Bumps [num_cpus](https://github.com/seanmonstar/num_cpus) from 1.13.1 to 1.14.0.
- [Release notes](https://github.com/seanmonstar/num_cpus/releases)
- [Changelog](https://github.com/seanmonstar/num_cpus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/num_cpus/compare/v1.13.1...v1.14.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 12:05:11 +00:00
Erik Krogh Kristensen
38bcb2b727 Merge pull request #12039 from github/dependabot/cargo/ql/serde-1.0.152
Bump serde from 1.0.140 to 1.0.152 in /ql
2023-01-31 13:03:03 +01:00
dependabot[bot]
198b97ca8d Bump serde from 1.0.140 to 1.0.152 in /ql
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.140 to 1.0.152.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.140...v1.0.152)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 11:48:44 +00:00
Erik Krogh Kristensen
f2526d1784 Merge pull request #12040 from github/dependabot/cargo/ql/tree-sitter-0.20.9
Bump tree-sitter from 0.20.8 to 0.20.9 in /ql
2023-01-31 12:46:43 +01:00
Gulshan Singh
1a109cab4d Remove unicode characters 2023-01-31 03:38:03 -08:00
dependabot[bot]
807b715320 Bump tree-sitter from 0.20.8 to 0.20.9 in /ql
Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.8 to 0.20.9.
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Commits](https://github.com/tree-sitter/tree-sitter/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 11:27:40 +00:00
Erik Krogh Kristensen
34ca12e5d2 Merge pull request #12042 from erik-krogh/qlTools
QL: update codeql-action in QL-for-QL
2023-01-31 12:24:37 +01:00
erik-krogh
94cec17505 bump codeql-action 2023-01-31 12:09:21 +01:00
erik-krogh
4436ec070e ensure the test is run when the workflow is updated 2023-01-31 12:09:21 +01:00
Geoffrey White
ee442e4d4b Merge pull request #11979 from geoffw0/modern1
Swift: Modernize injection queries
2023-01-31 10:54:35 +00:00
erik-krogh
0cefa98490 add missing word to the change-note 2023-01-31 11:53:17 +01:00
Mathias Vorreiter Pedersen
daf7d1b7e7 C++: Add more QLDoc. 2023-01-31 10:37:51 +00:00
Mathias Vorreiter Pedersen
7583fe2ad8 C++: Respond to PR reviews. 2023-01-31 10:31:02 +00:00
Tony Torralba
e9a46c926d Add taint for URLRequest fields 2023-01-31 11:15:45 +01:00
erik-krogh
95c19698c7 add change-note 2023-01-31 11:09:07 +01:00
erik-krogh
e5e8496084 fix QL-for-QL warnings 2023-01-31 10:55:27 +01:00
Arthur Baars
d944c2bd79 Ruby: address comments 2023-01-31 10:22:12 +01:00
Gulshan Singh
2f38d363ff Fix typo in dependsOnChild 2023-01-30 19:55:53 -08:00
Gulshan Singh
fb31570af3 Fix bitshift test 2023-01-30 19:55:53 -08:00
Gulshan Singh
1758e25207 Merge lshift/rshift range expressions into a single file and address PR comments 2023-01-30 19:55:53 -08:00
Gulshan Singh
051d36ee6a Add ConstantLShiftExprRange and ConstantRShiftExprRange classes 2023-01-30 19:55:53 -08:00
Gulshan Singh
5710289460 Add bitshift test 2023-01-30 19:55:53 -08:00
Harry Maclean
c99a096c9b Ruby: Update test fixtures 2023-01-31 11:27:19 +13:00
Harry Maclean
69ed00cdf1 Ruby: QL4QL fix 2023-01-31 11:06:32 +13:00
Mathias Vorreiter Pedersen
cd596403a0 Merge pull request #12031 from MathiasVP/ir-get-call-predicate 2023-01-30 21:23:02 +00:00
Chuan-kai Lin
396d2de6e7 Document pragma[assume_small_delta] 2023-01-30 11:42:57 -08:00
intrigus-lgtm
f23d517236 Fix errorneous slash
The additional slash causes the request to fail.
Compare `gh api /repos/openjdk/jdk/code-scanning/codeql/databases/` (fails) with:
```
gh api /repos/openjdk/jdk/code-scanning/codeql/databases/
{
  "message": "Not Found",
  "documentation_url": "https://docs.github.com/rest"
}
gh: Not Found (HTTP 404)
```
While `gh api /repos/openjdk/jdk/code-scanning/codeql/databases` (works).
2023-01-30 20:26:40 +01:00
Mathias Vorreiter Pedersen
a01a4734ed C++/C#: Sync identical files. 2023-01-30 17:32:53 +00:00
Mathias Vorreiter Pedersen
3a1a9a771c C++: Add a 'getCall' predicate to 'ArgumentOperand'. 2023-01-30 17:31:52 +00:00
Mathias Vorreiter Pedersen
f90007ae71 C++: Make our iterator models public. 2023-01-30 17:23:52 +00:00
erik-krogh
31743afa87 add change-note 2023-01-30 16:34:23 +01:00
erik-krogh
e01002368f add query detecting validators that use badly anchored regular expressions on library/remote input 2023-01-30 16:34:20 +01:00
Jami
7f6efae7dc Merge pull request #12008 from jcogs33/jcogs33/update-queryproducer-package
Java: update package for `QueryProducer` sinks
2023-01-30 10:27:58 -05:00
Alexander Eyers-Taylor
89d835b9ec Merge pull request #11988 from github/alexet/force-java-11
Use Java 11 for some integration tests
2023-01-30 15:19:00 +00:00
Nora Dimitrijević
fb88372c0f Merge pull request #11862 from d10c/swift/rename-iterabledeclcontext 2023-01-30 16:03:49 +01:00
AlexDenisov
48434f4be3 Merge pull request #12025 from github/alexdenisov/ignore-sandbox-exec
Swift: ignore sandbox-exec
2023-01-30 15:59:19 +01:00
erik-krogh
02da718786 add code-injection sink for node-pty 2023-01-30 15:14:25 +01:00
Alex Denisov
b71c5e6c4b Swift: ignore sandbox-exec 2023-01-30 15:10:30 +01:00
Erik Krogh Kristensen
862948f1cc Merge pull request #12014 from erik-krogh/axios
JS: add support for axios used as a global variable
2023-01-30 14:55:49 +01:00
Ian Lynagh
25e703e562 Merge pull request #11579 from igfoo/igfoo/only_lockless
Kotlin: Remove legacy trap-locking support
2023-01-30 13:44:31 +00:00
Michael Nebel
115a0a4318 C#: Add change note. 2023-01-30 14:28:35 +01:00
Michael Nebel
b25414fe93 C#: Add DB upgrade and downgrade scripts. 2023-01-30 14:28:35 +01:00
Michael Nebel
ff546c1497 C#: Add test cases for ref fields. 2023-01-30 14:28:35 +01:00
Michael Nebel
2be090bb91 C#: Add predicate isRef to the CIL Field class. 2023-01-30 14:28:35 +01:00
Michael Nebel
db047c2c4a C#: Extract CIL fields using their underlying types for a reference type field and annotate the field as a reference type. 2023-01-30 14:28:35 +01:00
Michael Nebel
812bc20812 C#: Add CIL fields as entities that can carry type annotations. 2023-01-30 14:28:35 +01:00
Michael Nebel
23acd5c255 C#: Small re-factor of the Modifier class. 2023-01-30 14:28:34 +01:00
Michael Nebel
3a4ec90ae9 C#: Extraction of ref modifier for fields. 2023-01-30 14:28:34 +01:00
Erik Krogh Kristensen
e46960e0cf Merge pull request #12022 from github/dependabot/cargo/ql/regex-1.7.1
Bump regex from 1.6.0 to 1.7.1 in /ql
2023-01-30 13:11:54 +01:00
dependabot[bot]
e3afb1640a Bump regex from 1.6.0 to 1.7.1 in /ql
Bumps [regex](https://github.com/rust-lang/regex) from 1.6.0 to 1.7.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.6.0...1.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 11:19:30 +00:00
Erik Krogh Kristensen
8198bbf893 Merge pull request #12019 from github/dependabot/cargo/ql/serde_json-1.0.91
Bump serde_json from 1.0.82 to 1.0.91 in /ql
2023-01-30 12:16:49 +01:00
Nora Dimitrijević
9346f4d760 Swift: fix failing tests 2023-01-30 11:39:06 +01:00
dependabot[bot]
f430e83fca Bump serde_json from 1.0.82 to 1.0.91 in /ql
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.82 to 1.0.91.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.82...v1.0.91)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 10:36:14 +00:00
Erik Krogh Kristensen
f647910e0c Merge pull request #12018 from erik-krogh/qlDependabot
QL: fixup the dependabot config for QL-for-QL
2023-01-30 11:35:05 +01:00
Erik Krogh Kristensen
78683e4e8a Merge pull request #11879 from erik-krogh/rbRegConcept
RB: add a RegexExecution concept, and use it for better regexp tracking
2023-01-30 11:33:09 +01:00
erik-krogh
40a576b775 fixup the dependabot config for QL-for-QL 2023-01-30 11:22:17 +01:00
erik-krogh
f04a9cb523 Merge branch 'main' into rbRegConcept 2023-01-30 11:05:40 +01:00
Erik Krogh Kristensen
3508a4b799 Merge pull request #12016 from erik-krogh/newEntity
QL: support the NewEntity module in QL-for-QL
2023-01-30 11:01:11 +01:00
Arthur Baars
907ebb723e Merge branch 'main' into json-log 2023-01-30 10:49:42 +01:00
erik-krogh
54c4c23b46 support the NewEntity module in QL-for-QL 2023-01-30 10:34:06 +01:00
Mathias Vorreiter Pedersen
6a8c570915 Merge pull request #12009 from MathiasVP/fix-fwd-flow-read-join
DataFlow: Fix join in `fwdFlowRead`
2023-01-30 09:23:43 +00:00
Harry Maclean
f7cdd430a2 Ruby: Small fix 2023-01-30 21:55:19 +13:00
Harry Maclean
7778524e08 Ruby: Refactor 2023-01-30 21:52:59 +13:00
Harry Maclean
5e9210fcea Ruby: use getAnAncestor 2023-01-30 21:21:38 +13:00
Harry Maclean
708e303c01 Ruby: Model except: with a const argument 2023-01-30 21:17:31 +13:00
Harry Maclean
28716866d8 Ruby: getAction -> getAnAction 2023-01-30 18:52:47 +13:00
Harry Maclean
246ad46eb1 Ruby: Account for filter skip ordering
A `skip_*_filter :foo` call only has an effect if there was an earlier
call that registered `:foo` as a filter.
2023-01-30 18:50:30 +13:00
Harry Maclean
a164e76a5d Ruby: Model actioncontroller filter overrides
If a filter is registered twice with the same name, the last
registration wins.
2023-01-30 18:05:22 +13:00
Harry Maclean
28c3bd3e2f Ruby: QL4QL fix 2023-01-30 17:41:36 +13:00
Harry Maclean
fb86ef4aac Ruby: Model ActionController filters
ActionController filters provide a way to register callbacks that run
before, after or around an action (i.e. HTTP request handler). They run
in the same class context as the action, so can get/set instance
variables and generally interact with the action in arbitrary ways.

In order to track flow between filters and actions, we have to model the
callback chain. This commit does that. A later change will add dataflow
steps to actually track flow through the chain.
2023-01-30 17:41:36 +13:00
erik-krogh
e3455a9b21 add support for axios used as a global variable 2023-01-29 22:55:20 +01:00
Nora Dimitrijević
d5f11dfe60 Swift: db upgrade/downgrade script 2023-01-28 00:44:49 +01:00
Nora Dimitrijević
1396d07662 Swift: subsume IterableDeclContext into Decl [tests] 2023-01-28 00:44:49 +01:00
Nora Dimitrijević
9a5614e8c5 Swift: subsume IterableDeclContext into Decl [codegen'd] 2023-01-28 00:44:49 +01:00
Nora Dimitrijević
f96c18a6db Swift: subsume IterableDeclContext into Decl [hand-written] 2023-01-28 00:44:48 +01:00
Mathias Vorreiter Pedersen
95b15825f9 DataFlow: Sync identical files. 2023-01-27 16:24:31 +00:00
Mathias Vorreiter Pedersen
a691535e77 C++: Fix join order in 'fwdFlowRead'. 2023-01-27 16:24:08 +00:00
Jami Cogswell
85c228a0cd Java: remove old sinks 2023-01-27 10:40:17 -05:00
Jami Cogswell
a3fe8c0e93 Java: add change note 2023-01-27 10:35:16 -05:00
Jami Cogswell
9bf43483db Java: update package for QueryProducer sinks 2023-01-27 10:16:42 -05:00
Geoffrey White
6c0b50c696 Merge pull request #11980 from geoffw0/modern2
Swift: Structure modernized queries more consistently
2023-01-27 14:33:43 +00:00
Geoffrey White
794ba428a7 Merge pull request #11942 from geoffw0/rncrypt4
Swift: add RNCryptor sinks to swift/static-initialization-vector
2023-01-27 14:33:06 +00:00
James Fletcher
812306cb52 Merge pull request #12006 from felickz/patch-2
Add link to codeql metadata article for problem.severity
2023-01-27 13:59:06 +00:00
alexet
1b0952c512 Use Java 11 for some integration tests 2023-01-27 13:51:44 +00:00
Chad Bentz
4fee536e6d table spacing 2023-01-27 08:19:43 -05:00
Chad Bentz
3ef4d3118c Add link to codeql metadata article for problem.severity 2023-01-27 08:01:07 -05:00
Ian Lynagh
75562e7fb5 Kotlin: Remove legacy trap-locking support 2023-01-26 16:58:51 +00:00
Nora
5993b60980 Update copy 2023-01-26 17:37:15 +01:00
Michael B. Gale
f192191e8c Merge pull request #11997 from github/smowton/fix/deperrors-conditional
Go: Fix DepErrors test
2023-01-26 14:52:27 +00:00
Mathias Vorreiter Pedersen
508027e0e5 Merge pull request #11998 from MathiasVP/fix-iterator-test 2023-01-26 12:35:12 +00:00
Mathias Vorreiter Pedersen
13baa5b60b C++: Add iterator typedefs to properly instantiate 'int_iterator_by_trait' and 'insert_iterator_by_trait'. 2023-01-26 11:43:33 +00:00
Chris Smowton
7921de243a Fix DepErrors test
This was likely harmlessly causing `go get` reruns, since most (all?) real dependency errors cause `go list` to exit with a nonzero return code in any case.
2023-01-26 11:37:41 +00:00
dependabot[bot]
295152cd32 Merge pull request #11992 from github/dependabot/cargo/ruby/serde-1.0.152 2023-01-26 10:17:56 +00:00
dependabot[bot]
bf02340a6a Merge pull request #11982 from github/dependabot/cargo/ruby/num_cpus-1.14.0 2023-01-26 10:13:09 +00:00
dependabot[bot]
6e69acdd7e Bump serde from 1.0.131 to 1.0.152 in /ruby
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.131 to 1.0.152.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.131...v1.0.152)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-26 03:08:58 +00:00
Harry Maclean
07a7a213b3 Merge pull request #11871 from hmac/rack 2023-01-26 08:40:30 +13:00
Rasmus Wriedt Larsen
1fcfae2464 Merge pull request #11987 from RasmusWL/suite-lists
Misc: Add `security-experimental` to `generate-code-scanning-query-list.py`
2023-01-25 17:29:36 +01:00
Geoffrey White
e92a5eb467 Merge pull request #11911 from geoffw0/rncrypt2
Swift: Add RNCryptor sinks to swift/hardcoded-key
2023-01-25 15:11:16 +00:00
Rasmus Wriedt Larsen
e8714c9edb Misc: Add Swift to generate-code-scanning-query-list.py 2023-01-25 15:22:20 +01:00
Rasmus Wriedt Larsen
b220c2f51d Misc: Add security-experimental to generate-code-scanning-query-list.py
Since not all experimental queries is part of this new suite, it's nice
to be able to list them explicitly without having to replicate the logic
from the .qls file.
2023-01-25 15:20:49 +01:00
Geoffrey White
f6fe627f4b Merge pull request #11914 from geoffw0/rncrypt3
Swift: Add RNCryptor sinks to swift/constant-salt
2023-01-25 13:05:33 +00:00
Alex Ford
3dd9392f5e Merge pull request #11869 from alexrford/rails/render_locals_shared
Ruby: Rails - generalize rails flow step for accessing render locals hash in view
2023-01-25 12:07:26 +00:00
Erik Krogh Kristensen
39e9eaf2bc Merge pull request #11986 from erik-krogh/redosNote2
RB: add note in ReDoS qhelp that Ruby 3.2 has fixed ReDoS
2023-01-25 11:56:04 +01:00
Paolo Tranquilli
f4cb920624 Merge pull request #11932 from github/redsun82/swift-docs
Swift: add and fix some `schema.py` documentation
2023-01-25 10:52:00 +01:00
Geoffrey White
fe13137b48 Swift: Make default implementations private. 2023-01-25 09:29:03 +00:00
erik-krogh
54b0350cac add note in ReDoS qhelp that Ruby 3.2 has fixed ReDoS 2023-01-25 10:24:11 +01:00
dependabot[bot]
531c0559a0 Bump num_cpus from 1.13.0 to 1.14.0 in /ruby
Bumps [num_cpus](https://github.com/seanmonstar/num_cpus) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/seanmonstar/num_cpus/releases)
- [Changelog](https://github.com/seanmonstar/num_cpus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/num_cpus/compare/v1.13.0...v1.14.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-25 08:48:08 +00:00
Arthur Baars
358ae7529b Merge pull request #11973 from github/dependabot/cargo/ruby/serde_json-1.0.91
Bump serde_json from 1.0.72 to 1.0.91 in /ruby
2023-01-25 09:45:32 +01:00
Arthur Baars
068b71bc3d Merge pull request #11972 from github/dependabot/cargo/ruby/regex-1.7.1
Bump regex from 1.5.5 to 1.7.1 in /ruby
2023-01-25 09:44:57 +01:00
Arthur Baars
e634ab771f Merge pull request #11971 from github/dependabot/cargo/ruby/flate2-1.0.25
Bump flate2 from 1.0.22 to 1.0.25 in /ruby
2023-01-25 09:44:29 +01:00
Erik Krogh Kristensen
99bad77972 Merge pull request #11906 from erik-krogh/moreStem
JS: expand what is parsed as the stem of a pathexpr
2023-01-25 08:44:44 +01:00
erik-krogh
80d05c0425 also recognize protected methods as library-input sources 2023-01-24 20:55:25 +01:00
erik-krogh
a017b7500b Merge branch 'main' into rbPoly 2023-01-24 20:51:36 +01:00
Geoffrey White
439d9199be Swift: Add CSV extension points. 2023-01-24 19:28:05 +00:00
Geoffrey White
13d308a4d6 Swift: Autoformat. 2023-01-24 19:15:51 +00:00
Geoffrey White
5375678ca6 Swift: Add consistent CSV extension points. 2023-01-24 18:49:50 +00:00
Geoffrey White
6a210d719b Swift: Rename QueryExtensions.qll files for consistency. 2023-01-24 17:58:13 +00:00
Paolo Tranquilli
ddef87f6e2 Merge pull request #10956 from github/redsun82/swift-linkage-awareness
Swift: disambuigate entities using linkage awareness on modules
2023-01-24 18:49:24 +01:00
Geoffrey White
6a946f6eed Swift: Modernize. 2023-01-24 17:26:51 +00:00
Paolo Tranquilli
4880ab41a2 Swift: use weakly_canonical instead of canonical
`weakly_canonical` will resolve as much as possible in the path, and not
return an error if it can't resolve everything (for example due to a
non existant file). In any case in case of problems with the file we
will see an error when actually using the resolved path.

This tunes down some unhelpful log messages.
2023-01-24 16:34:47 +01:00
Paolo Tranquilli
a74247e5d8 Swift: add filename to an error message 2023-01-24 16:29:10 +01:00
Paolo Tranquilli
6b77e6748a Swift: use same implementation for createTarget{Link,Object}Domain 2023-01-24 16:27:21 +01:00
Geoffrey White
78eff0dc60 Swift: Split off the Extensions.qll as well. 2023-01-24 15:19:41 +00:00
James Fletcher
176b2cae19 Merge pull request #11882 from github/charisk/rename-vscode-run-query-cmd
Rename VS Code Extension Run Query command
2023-01-24 15:17:30 +00:00
Geoffrey White
cbfa7e7252 Swift: Move query logic into .qlls. 2023-01-24 15:04:10 +00:00
Paolo Tranquilli
23344a7183 Merge branch 'main' into redsun82/swift-linkage-awareness 2023-01-24 15:47:44 +01:00
Jeroen Ketema
ae2fa6c1a4 Merge pull request #11975 from MathiasVP/another-dataflow-loop
C++: Add another looping dataflow test
2023-01-24 14:21:16 +01:00
Calum Grant
522c9d640d Merge pull request #11957 from github/yoff-list-support-for-python-3.11
Update supported-versions-compilers.rst
2023-01-24 10:15:11 +00:00
Mathias Vorreiter Pedersen
510211a4c7 C++: Add testcase with looping behavior in C/C++ def-use flow. 2023-01-24 09:44:30 +00:00
Michael Nebel
4df615f994 Merge pull request #11922 from michaelnebel/csharp11/strings
C# 11: String related functionality.
2023-01-24 10:31:31 +01:00
Michael Nebel
0b04654f33 C#: Update expected test output. 2023-01-24 09:51:47 +01:00
Michael Nebel
4c966f2b8a C#: Add some more UTF-8 encoded string examples. 2023-01-24 09:49:38 +01:00
Mathias Vorreiter Pedersen
ca5916f3dc Merge pull request #11946 from MathiasVP/fix-taint-models-2 2023-01-24 08:13:43 +00:00
dependabot[bot]
fd22c7c73e Bump serde_json from 1.0.72 to 1.0.91 in /ruby
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.72 to 1.0.91.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.72...v1.0.91)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 06:39:13 +00:00
dependabot[bot]
c4bf25f33c Bump regex from 1.5.5 to 1.7.1 in /ruby
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.5 to 1.7.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.5...1.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 06:39:09 +00:00
dependabot[bot]
b1f73b59cd Bump flate2 from 1.0.22 to 1.0.25 in /ruby
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.22 to 1.0.25.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.22...1.0.25)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 06:39:03 +00:00
Arthur Baars
c512eddb69 Merge pull request #11969 from hmac/simplify-ruby-dependabot-config
Ruby: Simplify dependabot config
2023-01-24 07:34:45 +01:00
Harry Maclean
8050639b16 Ruby: Simplify dependabot config
Dependabot is able to understand cargo workspaces, so it's not necessary
to enumerate each workspace member. It should be enough to configure it
with the workspace root directory. This will hopefully ensure that the
Cargo.lock file gets updated correctly.
2023-01-24 16:37:10 +13:00
Harry Maclean
e6e4e29bf8 Ruby: newline 2023-01-23 21:53:52 +00:00
Harry Maclean
224db456af Ruby: Simplify isRackResponse 2023-01-23 21:53:09 +00:00
Harry Maclean
60f9635ada Ruby: Move import 2023-01-23 21:51:27 +00:00
Harry Maclean
c1207e0938 Ruby: Fix rack response tracking
Use type tracking instead of getReturningNode, which seems to be faster
and works correctly for the cases I've tried.
2023-01-23 21:43:04 +00:00
erik-krogh
49f5e89f36 update expected output for experimental query 2023-01-23 22:29:49 +01:00
Erik Krogh Kristensen
fc66c905ff Merge pull request #11859 from erik-krogh/moreShell
JS: slightly broaden the regular expression that recognizes bad string-concats used as shell commands
2023-01-23 22:26:17 +01:00
Henry Mercer
21e63a8a86 Merge pull request #11967 from github/codeql-ci/atm/release-0.4.6
JS: Bump version numbers of ML-powered packs after 0.4.6 release
2023-01-23 20:43:18 +00:00
Henry Mercer
241951f53e Merge branch 'main' into codeql-ci/atm/release-0.4.6 2023-01-23 18:24:36 +00:00
github-actions[bot]
be481d975c JS: Bump version of ML-powered library and query packs to 0.4.7 2023-01-23 18:22:18 +00:00
github-actions[bot]
40a67d61d2 JS: Bump patch version of ML-powered library and query packs 2023-01-23 18:15:56 +00:00
Geoffrey White
25bcaa3a54 Merge pull request #11966 from geoffw0/usenumerics
Swift: Use numeric types in CleartextLogging.qll.
2023-01-23 18:06:17 +00:00
Sid Shankar
e32823c3e0 Merge pull request #11964 from github/sidshank/update-supported-language-versions-Jan-2023
Update supported language versions in documentation
2023-01-23 12:12:43 -05:00
Geoffrey White
19527016a5 Swift: Use numeric types in CleartextLogging.qll. 2023-01-23 16:52:03 +00:00
Geoffrey White
5ddff790b6 Swift: Autoformat. 2023-01-23 16:46:58 +00:00
Sid Shankar
f77d156e9a Update supported version of Java 2023-01-23 15:41:35 +00:00
Sid Shankar
444df6fccb Update supported version of Go 2023-01-23 15:41:02 +00:00
Erik Krogh Kristensen
240248b9cf Merge pull request #11453 from erik-krogh/unsafeHtmlConstruction
RB: add unsafe-html-construction query
2023-01-23 16:40:25 +01:00
erik-krogh
11894144aa remove regular expression that did nothing 2023-01-23 16:38:09 +01:00
Jeroen Ketema
0a0d6d0841 Merge pull request #11963 from MathiasVP/testcase-with-loop
C++: Add testcase with looping behavior
2023-01-23 16:33:36 +01:00
Erik Krogh Kristensen
5be97f3761 Merge pull request #11909 from erik-krogh/concatCode
Rb: recognize string concatenations as sinks for unsafe-code-construction
2023-01-23 16:22:46 +01:00
Mathias Vorreiter Pedersen
a217017859 C++: Add testcase with looping behavior in C/C++ use-use flow. 2023-01-23 14:29:39 +00:00
erik-krogh
ae00518ddf remove the isAdditionalTaintStep predicate from UnsafeHtmlConstructionQuery, as it was not needed 2023-01-23 15:27:19 +01:00
erik-krogh
7c6ee5f293 Merge branch 'main' into unsafeHtmlConstruction 2023-01-23 15:01:01 +01:00
Erik Krogh Kristensen
32c4cf5769 Apply suggestions from code review
Co-authored-by: Alex Ford <alexrford@users.noreply.github.com>
2023-01-23 14:58:04 +01:00
erik-krogh
800077dabe changes based on feedback 2023-01-23 14:54:36 +01:00
Erik Krogh Kristensen
a10b45e0db Merge pull request #11927 from mvogelgesang/express-rate-limit
JS: Updated express-rate-limit example to match implementation examples f…
2023-01-23 14:37:50 +01:00
Jeroen Ketema
05ecd2e015 Merge pull request #11958 from jketema/argv-if-tests
C++: Add some additional uncontrolled format string tests
2023-01-23 14:05:07 +01:00
erik-krogh
3cece50f78 add encodeURIComponent as a sanitizer for request-forgery 2023-01-23 13:53:53 +01:00
erik-krogh
be8ef1b324 add failing test 2023-01-23 13:52:36 +01:00
Erik Krogh Kristensen
45aaeb897a Merge pull request #11955 from erik-krogh/docFrameworks
JS: add Fastify and restify to the list of supported frameworks
2023-01-23 13:14:15 +01:00
Philip Ginsbach
78a2dfa7c4 Merge pull request #11939 from github/ginsbach/DocumentNewNamespaces
document new namespaces
2023-01-23 12:12:49 +00:00
Chris Smowton
fea97a22c6 Merge pull request #11827 from smowton/smowton/admin/test-gradle-script-parsing
Java: Add integration tests for Android projects
2023-01-23 11:39:24 +00:00
Philip Ginsbach
8a3972049b fix grammar 2023-01-23 11:15:22 +00:00
Jeroen Ketema
cfc0dabad9 C++: Add some additional uncontrolled format string tests
These duplicate the `i9` and `i91` tests slightly earlier in the same file, but
use an explicit `if` instead of the ternary operator.
2023-01-23 11:50:45 +01:00
Mathias Vorreiter Pedersen
470abfd0aa C++: Conflate iterator value and indirection for taint-flow to fix AST dataflow. 2023-01-23 10:40:25 +00:00
yoff
fe0290fb39 Update supported-versions-compilers.rst
List 3.11 as supported for Python
2023-01-23 11:33:32 +01:00
Mathias Vorreiter Pedersen
962b651c44 C++: Fix models. 2023-01-23 10:10:02 +00:00
Alex Ford
3b10a2de11 Merge branch 'main' into rails/render_locals_shared 2023-01-23 10:00:22 +00:00
Alex Ford
55550e7980 Merge pull request #11941 from alexrford/summary-component-tostring-syntheticglobal
Add missing toString case for synthetic globals
2023-01-23 10:00:00 +00:00
Erik Krogh Kristensen
1ee9957838 Merge pull request #9807 from erik-krogh/endFilter
JS: recognize "-->" as a bad tag filter
2023-01-23 10:06:50 +01:00
Arthur Baars
99148244a4 Merge pull request #11856 from aibaars/update-grammars
Update grammars
2023-01-23 09:46:50 +01:00
erik-krogh
dc1bfa3a04 add Fastify and restify to the list of supported frameworks 2023-01-23 09:36:49 +01:00
Michael Nebel
69a42d8b1f Merge pull request #11931 from michaelnebel/csharp/refactor
Remove the Csv postfix of some predicate names.
2023-01-23 09:09:48 +01:00
Michael Nebel
440fe80c14 C#: Update stats. 2023-01-23 09:06:34 +01:00
Harry Maclean
21ce9b448a Ruby: Attempt to fix performance of AppCandidate
`DataFlow::MethodNode.getAReturningNode` is expensive to compute.
Instead we look for rack responses which flow to the `SynthReturnNode`.
Each method has only one of these (vs many "returning" nodes) so it is
a lot faster.
I'm not sure yet whether the results are the same.
2023-01-23 15:25:52 +13:00
Chris Smowton
a2e7b83411 Add additional note to Android tests 2023-01-21 11:57:54 +00:00
Chris Smowton
81e59e9005 Force Gradle tests to run sequentially
Otherwise starting multiple Gradle daemons in parallel can fail
2023-01-21 11:57:53 +00:00
Chris Smowton
4197d7bd20 Android tests: use Java 11 under Actions
Some runners still default to Java 8 (e.g. windows-2022 and macos-12), so we need to manually pull Java 11 in in such cases.
2023-01-21 11:57:53 +00:00
Chris Smowton
b6df415fe8 Add Android and Kotlin build script tests
This adds a single plain Gradle project that uses a modern Kotlin build script (i.e. settings.gradle.kts and no build.gradle.kts), plus basic Android samples exercising the possible permutations of: (old vs. new-style build script, Groovy vs. Kotlin build script, wrapper present vs. absent)

Old vs. new style tests our recognition of different cues that this is likely a Droid project and requires `gradle assemble` not `gradle testClasses` (the example given at https://developer.android.com/studio/build/#top-level changed style as of plugin version ~7.3.0).

Groovy vs. Kotlin build script language checks that the regexes recognising Android dependencies and versions work for both build script kinds.

Wrapper present vs. absent exercises the autobuilder logic that guesses an appropriate Gradle version and sets it up in the event the Gradle wrapper isn't provided.
2023-01-21 11:57:53 +00:00
Mathias Vorreiter Pedersen
e664662df9 Merge pull request #11944 from github/post-release-prep/codeql-cli-2.12.1
Post-release preparation for codeql-cli-2.12.1
2023-01-20 21:52:55 +00:00
github-actions[bot]
b62cb6ba84 Post-release preparation for codeql-cli-2.12.1 2023-01-20 19:49:56 +00:00
Arthur Baars
2b9bc3c7e3 Ruby: write errors to json log 2023-01-20 20:11:55 +01:00
Sarita Iyer
f5406570f7 Merge pull request #11817 from github/saritai/docs-contributing-info
Add CONTRIBUTING.MD file for contributing to docs
2023-01-20 12:41:20 -05:00
Geoffrey White
f05be77a0b Swift: Recognize more array sources. 2023-01-20 15:25:00 +00:00
Geoffrey White
7648e8f6a3 Swift: Recognize more sources. 2023-01-20 15:08:12 +00:00
Jean Helie
9e6f9c2705 Merge pull request #11709 from github/jhelie/add-shell-command-injection
ATM: add boosted version for `ShellCommandInjectionFromEnvironment` query
2023-01-20 16:03:30 +01:00
Geoffrey White
581c478872 Swift: Model RNCryptor. 2023-01-20 14:50:23 +00:00
Geoffrey White
bb59d055ff Swift: Add tests for RNCryptor library. 2023-01-20 14:50:21 +00:00
Mathias Vorreiter Pedersen
3059ce3070 Merge pull request #11938 from github/release-prep/2.12.1
Release preparation for version 2.12.1
2023-01-20 14:30:42 +00:00
Alex Ford
8ae993185c Ruby: fix missing docs 2023-01-20 13:40:19 +00:00
Alex Ford
c986ea1070 Ruby: scope local_assigns synthetic globals to both render call and template file 2023-01-20 13:40:19 +00:00
Alex Ford
14c896215c Ruby: factor out some RenderCall methods into a helper module 2023-01-20 13:40:19 +00:00
Alex Ford
03070c9fd0 Ruby: restrict AccessLocalsKeySummary to method calls against self 2023-01-20 13:40:19 +00:00
Alex Ford
f6516db105 Ruby: correct preservesValue in AccessLocalsKeySummary 2023-01-20 13:40:19 +00:00
Alex Ford
ab72301a4c Ruby: add a change note for rails render locals dataflow 2023-01-20 13:40:19 +00:00
Alex Ford
8fec4b804f Ruby: StoredXSS test whitespace change 2023-01-20 13:40:19 +00:00
Alex Ford
fd8dd5e103 Ruby: update StoredXSS test output 2023-01-20 13:40:19 +00:00
Alex Ford
8845157d08 Ruby: slightly limit AccessLocalsKeySummary summarized callables 2023-01-20 13:40:19 +00:00
Alex Ford
b5cc1087fe Ruby: add LocalAssignsHashSyntheticGlobal#getARenderCall predicate 2023-01-20 13:40:19 +00:00
Alex Ford
022171923c Ruby: fix some ql for ql alerts 2023-01-20 13:40:19 +00:00
Alex Ford
bea110b598 Ruby: remove blank line in test file 2023-01-20 13:40:19 +00:00
Alex Ford
b78ae1608e Ruby: remove a fixed TODO 2023-01-20 13:40:19 +00:00
Alex Ford
e5fbc92856 Ruby: generalize rails flow step for accessing render locals hash in view 2023-01-20 13:40:19 +00:00
Alex Ford
e4df1f5a6f Ruby: add missing toString case for synthetic globals 2023-01-20 13:31:43 +00:00
Jeroen Ketema
cddaa0c8fa Apply suggestions from code review 2023-01-20 14:10:27 +01:00
Michael Nebel
4d321d6833 C#: Add upgrade and downgrade scripts. 2023-01-20 13:39:41 +01:00
Michael Nebel
6c7c0854d1 C#: Add change note. 2023-01-20 13:39:41 +01:00
Michael Nebel
5a1e96d671 C#: Update string literal test query and expected output. 2023-01-20 13:39:41 +01:00
Michael Nebel
5c5d330704 C#: Add UTF-8 encoded string test case. 2023-01-20 13:39:41 +01:00
Michael Nebel
20398f1299 C#: Add PrintAst testcase for C# 11 test code. 2023-01-20 13:39:41 +01:00
Michael Nebel
c52dbcbb52 C#: Update all PrintAst test expected output. 2023-01-20 13:39:41 +01:00
Michael Nebel
c87668a91d C#: Library support for string UTF8/UTF16 encodings. 2023-01-20 13:39:41 +01:00
Michael Nebel
e8eedb7b4d C#: Extractor support for UTF-8 encoded strings. 2023-01-20 13:39:41 +01:00
Michael Nebel
72fa3bd905 C#: Add test cases for raw string literals. 2023-01-20 13:39:41 +01:00
Michael Nebel
3b93cd45ea C#: Extract the ValueText instead of Text for interpolated string literals as this contains the value after eg. indentation processing. 2023-01-20 13:39:41 +01:00
Michael Nebel
ad20e81d05 C#: Add test for interpolated strings, where newlines are used in the provided expression. 2023-01-20 13:39:41 +01:00
Philip Ginsbach
3998c9a89a document the existence of a global QlBuiltins module 2023-01-20 12:16:24 +00:00
Philip Ginsbach
127b1ac114 update handbook and reference with signature namespaces 2023-01-20 12:16:22 +00:00
github-actions[bot]
005b3e4a47 Release preparation for version 2.12.1 2023-01-20 12:03:19 +00:00
Geoffrey White
976b0401be Merge pull request #11876 from geoffw0/coredata
Swift: Improve Core Data sinks for swift/cleartext-storage-database
2023-01-20 11:02:03 +00:00
Harry Maclean
16baea22c0 Ruby: doc fix
Co-authored-by: Alex Ford <alexrford@users.noreply.github.com>
2023-01-20 22:06:29 +13:00
Paolo Tranquilli
1c086aae7c Swift: add internal imports to ParentChild.qll 2023-01-20 09:59:36 +01:00
Ian Lynagh
05c80b3f3c Merge pull request #11894 from igfoo/igfoo/make-private
Kotlin: Make a couple of functions private
2023-01-19 20:59:32 +00:00
Sarita Iyer
3a8479614b fix link 2023-01-19 15:13:34 -05:00
Paolo Tranquilli
e840b8f707 Swift: add and fix some schema.py documentation 2023-01-19 18:07:47 +01:00
Ian Lynagh
c2d5281e73 Merge pull request #11930 from igfoo/igfoo/fetch-codeql
CI: fetch-codeql: Set $CODEQL_FETCHED_CODEQL_PATH in the enivironment
2023-01-19 15:33:08 +00:00
Sarita Iyer
a83a98226c Update README.rst 2023-01-19 09:45:43 -05:00
Sarita Iyer
27a5051282 Update README.md 2023-01-19 09:45:01 -05:00
Sarita Iyer
894a494186 Apply suggestions from code review
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com>
2023-01-19 09:39:55 -05:00
Paolo Tranquilli
c2c14cdddb Merge pull request #11929 from github/redsun82/swift-expand-ref-in-auto-docs
Swift: expand `ref` in autogenerated docs
2023-01-19 15:24:05 +01:00
Michael B. Gale
14cc27e49b Merge pull request #11910 from owen-mc/go/log-injection-sanitizer-newreplacer-replace
Add missing string replacement sanitizers to log-injection and string-break
2023-01-19 14:23:03 +00:00
Michael Nebel
dc223cb82e Sync files and make corresponding changes for other languages. 2023-01-19 15:14:06 +01:00
Chris Smowton
9a5e1f5e28 Make import private 2023-01-19 14:10:17 +00:00
Michael Nebel
9cd1dc70e5 C#: Remove the Csv postfix of some predicates. 2023-01-19 15:02:52 +01:00
Owen Mansel-Chan
13d1c88a11 Make new data flow copy for StringOps.StringsNewReplacer 2023-01-19 13:05:31 +00:00
Arthur Baars
d5e60dfb22 Ruby: pass diagnostics::LogWriter to extractor 2023-01-19 13:53:56 +01:00
Geoffrey White
62125fa767 Swift: Explanatory comments. 2023-01-19 11:55:16 +00:00
Ian Lynagh
3a5bec5778 CI: fetch-codeql: Set $CODEQL_FETCHED_CODEQL_PATH in the enivironment 2023-01-19 11:37:05 +00:00
Geoffrey White
2875d8645c Swift: Cover additional edge case. 2023-01-19 11:34:07 +00:00
Geoffrey White
4c47de58c1 Swift: Add a few more test cases. 2023-01-19 11:27:44 +00:00
Geoffrey White
5f8875ff89 Swift: give variables more helpful names. 2023-01-19 10:31:23 +00:00
Geoffrey White
b033114f64 Swift: sources in extension protocols. 2023-01-19 10:04:04 +00:00
Paolo Tranquilli
57ec5db1a9 Merge branch 'main' into redsun82/swift-linkage-awareness 2023-01-19 10:49:33 +01:00
Paolo Tranquilli
490bd051cd Swift: expand ref in autogenerated docs 2023-01-19 09:27:44 +00:00
Michael Nebel
e6aebd9df0 Merge pull request #11814 from michaelnebel/csharp/genericattributes
C# 11: Generic attributes
2023-01-19 07:35:17 +01:00
Erik Krogh Kristensen
ee9b01b5e6 Apply suggestions from code review
Co-authored-by: Alex Ford <alexrford@users.noreply.github.com>
2023-01-18 22:14:46 +01:00
Mark Vogelgesang
a3ff0725a3 Removed change-note as it was not necessary 2023-01-18 16:08:29 -05:00
Mark Vogelgesang
e50a81cbb7 Merge branch 'main' into express-rate-limit 2023-01-18 14:44:29 -05:00
Mark Vogelgesang
c9119848d9 Updated express-rate-limit example to match implementation examples found on packages README 2023-01-18 14:42:40 -05:00
Mathias Vorreiter Pedersen
14468b64fb Merge pull request #11924 from atorralba/atorralba/optbinding-getters
Swift: Support more CFG node types in optional binding flow
2023-01-18 16:37:11 +00:00
Owen Mansel-Chan
3fda9f6e65 Add change note 2023-01-18 15:42:42 +00:00
Arthur Baars
e85e61b6d7 Ruby: add diagnostics module 2023-01-18 16:28:16 +01:00
Owen Mansel-Chan
30f0dd8c03 Add string replacement sanitizer to log injection 2023-01-18 15:24:39 +00:00
Owen Mansel-Chan
015ef4c3ef Add use of strings.Replacer to replace sanitizer 2023-01-18 15:20:14 +00:00
Owen Mansel-Chan
2b1a7898d9 Move ReplaceAll sanitizer to shared code 2023-01-18 15:12:52 +00:00
AlexDenisov
5173f10e68 Merge pull request #11925 from github/alexdenisov/swift-drop-dead-code
Swift: drop dead code
2023-01-18 16:10:25 +01:00
Alex Denisov
35620c4c86 Swift: drop dead code 2023-01-18 15:35:40 +01:00
Mathias Vorreiter Pedersen
e26e83b8df Merge pull request #11728 from github/rdmarsh2/parameterize-range-analysis
C++: Parameterize the semantic range analysis
2023-01-18 14:22:35 +00:00
Geoffrey White
5d6f2436e4 Merge branch 'main' into coredata 2023-01-18 13:39:02 +00:00
Tony Torralba
90517e254a Accept test expectation changes 2023-01-18 13:25:04 +01:00
Mathias Vorreiter Pedersen
48439bc252 Merge pull request #11905 from geoffw0/rncrypt
Swift: Add RNCryptor sinks to swift/constant-password
2023-01-18 11:43:23 +00:00
Tony Torralba
d75a5212b2 Support more CFG node types in optional binding flow 2023-01-18 12:42:44 +01:00
Tony Torralba
4a89a30abd Add failing test 2023-01-18 12:41:59 +01:00
Mathias Vorreiter Pedersen
c8bcfb77b2 Merge pull request #11836 from geoffw0/optbinding
Swift: Data flow through optional binding
2023-01-18 11:25:27 +00:00
Geoffrey White
71c1ca53a9 Merge branch 'main' into rncrypt 2023-01-18 11:09:09 +00:00
erik-krogh
e4d4873d0d remove the dataflow copy for regexp tracking now that type-tracking is used 2023-01-18 11:04:51 +01:00
Michael Nebel
4c94adb5ec C#: Add change note. 2023-01-18 10:50:04 +01:00
Michael Nebel
3846349ba0 C#: Add testcase for CIL generic attribute extraction. 2023-01-18 10:49:44 +01:00
Michael Nebel
821d294be8 C#: Add library support for CIL generic attributes. 2023-01-18 10:49:44 +01:00
Michael Nebel
5ff89a2ccf C#: Update expected test output for printing of constructed generic CIL types. 2023-01-18 10:49:44 +01:00
Michael Nebel
8b231c51f9 C#: Improve printing of constructed generic CIL types. 2023-01-18 10:49:44 +01:00
Michael Nebel
b680795d15 C#: The generic attribute type is a constructed class. 2023-01-18 10:49:44 +01:00
Michael Nebel
62e7c22783 C#: Add generic attribute test and expected results. 2023-01-18 10:48:30 +01:00
Michael Nebel
211af1943c C#: Library support for generic attributes. 2023-01-18 10:48:30 +01:00
Michael Nebel
3a4623b437 Merge pull request #11907 from michaelnebel/csharp/cil/attributes
C#: CIL attributes
2023-01-18 10:46:34 +01:00
Rasmus Wriedt Larsen
e0ccb9306a Merge pull request #11908 from RasmusWL/dataflow-consistency-more-excludes
DataFlow: Add `uniqueParameterNodePositionExclude`
2023-01-18 10:44:51 +01:00
AlexDenisov
8910ba4f32 Merge pull request #11919 from github/redsun82/swift-obsolete-conf
Swift: remove obsolete configuration fields
2023-01-18 10:34:24 +01:00
erik-krogh
1477974bf1 the RegexExecution concept does not need to have getTerm() 2023-01-18 10:10:36 +01:00
erik-krogh
1a3c9c8305 improve performance of regular-expression type-tracking by adding an exploratory initial analysis 2023-01-18 10:10:36 +01:00
erik-krogh
b8f6feb68b delete old test 2023-01-18 10:10:36 +01:00
erik-krogh
45316b6381 rename RegExpConfiguration to RegExpTracking 2023-01-18 10:10:36 +01:00
erik-krogh
25e65e0d9f rewrite the regexp tracking DataFlow::Configuration to TypeTracking 2023-01-18 10:10:36 +01:00
erik-krogh
d0b627b018 move the implementation detail of how regular-expressions are tracked into RegExpConfiguration.qll" 2023-01-18 10:10:05 +01:00
Paolo Tranquilli
f383fd1dc1 Swift: introduce module disambuigation via linkage awareness 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
d7feb001be Swift: prepare extractSwiftInvocation 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
a3b4c32f07 Swift: stamp all named declarations with an id-ref to the containing module 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
f7a046ccd2 Swift: add trap linkage awareness infrastructure 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
5fdb09380c Swift: move TargetTrapDomain to TargetDomains in infra 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
7f389b9f9a Swift: introduce TrapType 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
353536b826 Swift: collect original output module paths 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
84b285a4c6 Swift: collect source files 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
33c4a8233c Swift: collect encountered modules 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
c7f13f1036 Swift: collect TRAP files related to an extractor run
In order to do this a mutable `SwiftExtractorState` is introduced.
2023-01-18 10:07:46 +01:00
Paolo Tranquilli
c31c515205 Swift: move TargetFile as managed inside TrapDomain 2023-01-18 10:07:46 +01:00
Paolo Tranquilli
20eaa34485 Swift: failing tests for linkage awareness 2023-01-18 10:07:46 +01:00
Tony Torralba
c8e894b854 Merge pull request #11917 from github/workflow/coverage/update
Update CSV framework coverage reports
2023-01-18 10:02:22 +01:00
erik-krogh
f516ccb4e2 limit the fieldFlowBranchLimit for the regexp tracker to improve performance 2023-01-18 09:31:04 +01:00
erik-krogh
2fceee4e35 track regular expressions that gets compiled with Regexp.compile 2023-01-18 09:31:04 +01:00
erik-krogh
acf28ebd98 add a RegexExecution, and use it to track regular expressions to their uses in a nice way in rb/polynomial-redos 2023-01-18 09:31:04 +01:00
erik-krogh
6e33dd5df6 add failing test 2023-01-18 09:31:04 +01:00
Erik Krogh Kristensen
1a64393c4c Merge pull request #11893 from erik-krogh/csharpIndexFiles
C#: add --working-dir=. to pre-finalize
2023-01-18 09:05:29 +01:00
Paolo Tranquilli
2c4c2dfeb3 Swift: remove obsolete configuration fields 2023-01-18 08:55:59 +01:00
Michael Nebel
8e3e6505ad C#: Add change note. 2023-01-18 07:56:24 +01:00
github-actions[bot]
571942fb21 Add changed framework coverage reports 2023-01-18 00:17:19 +00:00
Jeroen Ketema
6cd52237c3 Merge pull request #11913 from jketema/test-fixes
C++: Some minor test fixes
2023-01-17 21:52:57 +01:00
erik-krogh
4b74dec18f expand what is parsed as the stem of a pathexpr 2023-01-17 21:28:21 +01:00
yoff
5a82012d03 Merge pull request #11854 from yoff/python/fix-tarslip-improv-bug
Python: fix bug  in `py/tarslip-extended`
2023-01-17 20:44:06 +01:00
Geoffrey White
a568d0af7f Swift: Remove unused variable. 2023-01-17 18:10:02 +00:00
Geoffrey White
b3d30bfc4f Swift: Add NumberLiteral sources as well. 2023-01-17 18:04:26 +00:00
Jeroen Ketema
ee19c3d80f C++: Rename identically named classes in syntax-zoo
Conceptually the test that comprises the whole of `syntax-zoo` forms one
single binary. To this binary ODR applies. There were two class definitions
`Foo` in `syntax-zoo`, violating ODR. Rename those classes to have different
names.
2023-01-17 19:02:40 +01:00
Jeroen Ketema
06767c6760 C++: Split bad_asts.cpp IR test into two files
The statements from `errorExpr` - which does not parse correctly - affected the
tuples that were being generated for the other code in `bad_asts.cpp` due to
the way the front-end handles parse errors. This did not affect the test
results, but was also not the intention of the test. Split off `errorExpr` into
a separate file.
2023-01-17 18:57:29 +01:00
Geoffrey White
d1cfdb97ee Swift: Model RNCryptor. 2023-01-17 17:55:52 +00:00
Sarita Iyer
c8298356dc Rename CONTRIBUTING.MD to CONTRIBUTING.md 2023-01-17 12:32:36 -05:00
Geoffrey White
a92e1c7ea0 Swift: Add tests for RNCryptor library. 2023-01-17 17:31:49 +00:00
Geoffrey White
5e5c4e9a8c Swift: Accept QL-for-QL recommendation. 2023-01-17 16:25:34 +00:00
Geoffrey White
9911dd53e1 Merge branch 'main' into coredata 2023-01-17 16:22:53 +00:00
Geoffrey White
ea06ad1933 Merge pull request #11529 from geoffw0/format
Swift: Uncontrolled format string query
2023-01-17 16:16:10 +00:00
Geoffrey White
3c55cdd5be Swift: Catch the last two test results as well. 2023-01-17 16:04:58 +00:00
Geoffrey White
d42848bb7e Swift: Upgrade the query from dataflow to taint tracking, so as to support more flows. 2023-01-17 16:04:58 +00:00
Geoffrey White
28a707a956 Swift: Model RNCryptor. 2023-01-17 16:04:58 +00:00
Geoffrey White
a8ef9cc987 Swift: Add tests for RNCryptor library. 2023-01-17 16:04:57 +00:00
Edward Minnix III
4c018759c8 Merge pull request #11283 from egregius313/egregius313/webview-setAllowContentAccess
Java: Android WebView Content Access Query
2023-01-17 11:02:47 -05:00
Michael Nebel
62533501fe C#: Update CIL attributes test case and the expected output. 2023-01-17 17:00:01 +01:00
Geoffrey White
54b3262d9c Merge pull request #11891 from geoffw0/authbypass
C++: Fix issue with cpp/user-controlled-bypass
2023-01-17 15:43:08 +00:00
Jami
babdee36aa Merge pull request #11779 from jcogs33/jcogs33/model-more-top-jdk-apis
Java: model top JDK APIs
2023-01-17 10:20:32 -05:00
Geoffrey White
d628cc5ab8 Update cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2023-01-17 14:37:19 +00:00
erik-krogh
8251ad5e99 add unsafe-html-construction query 2023-01-17 15:35:17 +01:00
erik-krogh
8715790fe7 add explicit this 2023-01-17 15:17:48 +01:00
Geoffrey White
037b49b454 Update swift/ql/test/query-tests/Security/CWE-259/rncryptor.swift
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2023-01-17 14:16:52 +00:00
Paolo Tranquilli
6b43ff45a4 Merge pull request #11904 from github/redsun82/swift-extension-protocols
Swift: extract `ExtensionDecl` protocols
2023-01-17 15:16:20 +01:00
Paolo Tranquilli
d9bd41b8b1 Merge pull request #11571 from github/redsun82/swift-open-redirection
Swift: generalize open redirection on both platforms and rework output rewriting
2023-01-17 15:15:56 +01:00
Jami Cogswell
10f0975812 Java: remove models for System.[get|set]Property 2023-01-17 08:51:48 -05:00
erik-krogh
a562568522 add string concat as a sink for command-construction 2023-01-17 14:48:09 +01:00
erik-krogh
9d9de18bc9 add a generalized AddExprRoot into Operation.qll 2023-01-17 14:48:08 +01:00
erik-krogh
8fc3b268e8 add string concat as a sink for code-construction 2023-01-17 14:48:06 +01:00
Paolo Tranquilli
9e5db7c6ec Merge branch 'main' into redsun82/swift-extension-protocols 2023-01-17 14:39:09 +01:00
Michael Nebel
5f57a097ab C#: CIL method attribute extraction. 2023-01-17 14:17:35 +01:00
Michael Nebel
951f6362aa Merge pull request #11825 from michaelnebel/csharp/genericmathsupport
C# 11: Support for static virtual and static abstract interface members.
2023-01-17 14:14:02 +01:00
Rasmus Wriedt Larsen
a0b1c2ea79 DataFlow: Add uniqueParameterNodePositionExclude 2023-01-17 14:05:22 +01:00
Rasmus Wriedt Larsen
2b0a5fd5d1 DataFlow: Add uniqueParameterNodeAtPositionExclude 2023-01-17 14:05:17 +01:00
Erik Krogh Kristensen
2e4f4c64fe Merge pull request #11903 from erik-krogh/revertClap
QL: Revert "update clap to 3.0 in QL-for-QL"
2023-01-17 13:29:04 +01:00
Paolo Tranquilli
0a792f2f61 Swift: add upgrade and downgrade scripts for ExtensionDecl new protocols property 2023-01-17 13:07:02 +01:00
Paolo Tranquilli
0d32f00020 Swift: update ExtensionDecl test results 2023-01-17 12:58:02 +01:00
Paolo Tranquilli
d6e0ef9ff9 Swift: extract ExtensionDecl protocols 2023-01-17 12:56:09 +01:00
Paolo Tranquilli
f6e26211f9 Swift: add protocols to ExtensionDecl schema 2023-01-17 12:54:50 +01:00
Geoffrey White
74a37475db Swift: Model RNCryptor. 2023-01-17 11:54:12 +00:00
Mathias Vorreiter Pedersen
44ebc77ada Update cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisSpecific.qll 2023-01-17 11:52:43 +00:00
Paolo Tranquilli
8906e101cb Swift: add ExtensionDecl QL test 2023-01-17 12:49:53 +01:00
erik-krogh
5a4fe71529 Revert "update clap to 3.0 in QL-for-QL"
This reverts commit d072ed969e.
2023-01-17 12:38:30 +01:00
Erik Krogh Kristensen
50b9f5bba0 Merge pull request #11892 from erik-krogh/clap
QL: update clap to 3.0 in QL-for-QL
2023-01-17 12:33:18 +01:00
Jean Helie
fec7ea6964 ATM: add missing query help files 2023-01-17 12:20:17 +01:00
Jean Helie
b08fa43fdf update tests 2023-01-17 12:20:17 +01:00
Jean Helie
f07984bab2 update test data 2023-01-17 12:20:17 +01:00
Jean Helie
13aaa22df5 add bosted version of ShellCommandInjectionFromEnvironment 2023-01-17 12:20:17 +01:00
Mathias Vorreiter Pedersen
77a9cea737 Merge pull request #11901 from github/redsun82/swift-ql-internal
Swift: introduce `@ql.internal` pragma for classes
2023-01-17 10:46:56 +00:00
Paolo Tranquilli
67bd8cba32 Merge pull request #11900 from github/alexdenisov/swift-ignore-lsregister
Swift: do not trace lsregister
2023-01-17 11:26:22 +01:00
Chris Smowton
29425982a5 Merge pull request #11899 from ataillefer/patch-1
Fix partial path traversal Java example
2023-01-17 09:39:36 +00:00
Paolo Tranquilli
6106edd5e2 Swift: add INTERNAL doc marker to ql.internal classes 2023-01-17 10:30:59 +01:00
Paolo Tranquilli
b22da25e05 Swift: remove ql.internal classes from global import 2023-01-17 10:18:03 +01:00
Paolo Tranquilli
48825442c3 Swift: add ql.internal pragma in schema definitions 2023-01-17 10:10:35 +01:00
Paolo Tranquilli
cdc99b5240 Swift: simplify pragma definition 2023-01-17 10:10:02 +01:00
Geoffrey White
449ebb8a12 Swift: Add tests for RNCryptor library. 2023-01-17 09:03:07 +00:00
Paolo Tranquilli
e3502e2e5f Merge branch 'main' into redsun82/swift-open-redirection 2023-01-17 09:43:00 +01:00
Alex Denisov
63b4e5ef5c Swift: do not trace lsregister 2023-01-17 09:26:31 +01:00
Erik Krogh Kristensen
51bd1ef1e1 Merge pull request #11884 from erik-krogh/qlWin
QL/Ryby: fix qltest on Windows
2023-01-16 21:57:01 +01:00
Antoine Taillefer
660e6d7085 Fix partial path traversal Java example
The Java recommendation example for the "Partial path traversal vulnerability from remote" query doesn't seem right to me. Indeed, the following statement doesn't compile, since `dir.getCanonicalPath()` returns a String:
```
dir.getCanonicalPath().toPath()
```
Maybe the author wanted to state `dir.getCanonicalFile().toPath()`, which would compile, but is useless compared to `dir.getCanonicalPath()`.

Moreover, `parent.getCanonicalFile().toPath()` or `parent.getCanonicalPath()` will **not** be slash-terminated, contrary to what the description says.
From what I can see (and test), the correct fix is to concatenate `File.separator` to the parent canonical path.
2023-01-16 21:14:29 +01:00
erik-krogh
dcc1c3d487 add --working-dir=. to pre-finalize for c# 2023-01-16 18:09:00 +01:00
Ian Lynagh
17de5c120a Kotlin: Make a couple of functions private 2023-01-16 15:29:14 +00:00
Tony Torralba
bd5619147d Merge pull request #11590 from atorralba/atorralba/swift/sensitive-info-logs
Swift: Add Cleartext Logging query
2023-01-16 16:22:20 +01:00
erik-krogh
713599963b add --working-dir to Ruby qltest.cmd to fix Windows 2023-01-16 15:37:35 +01:00
erik-krogh
9e153cfb0d change the Ruby-build test such that Windows fails 2023-01-16 15:37:35 +01:00
erik-krogh
587adea809 QL: add --working-dir to qltest.cmd to fix qltest 2023-01-16 15:37:14 +01:00
erik-krogh
2c1ecb507d fix windows 2023-01-16 15:36:57 +01:00
erik-krogh
1de65131fe add compilation cache to QL-for-QL tests 2023-01-16 15:36:57 +01:00
erik-krogh
0685732e3f delete ql/ specific format step now that we have an all-languages format check 2023-01-16 15:36:57 +01:00
erik-krogh
1d62751e15 test QL-for-QL on mac/win 2023-01-16 15:36:55 +01:00
Tony Torralba
0017461e2d Update swift/ql/src/queries/Security/CWE-312/CleartextLogging.ql
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2023-01-16 15:35:58 +01:00
Tony Torralba
cca6a13fbb Update java/ql/src/Security/CWE/CWE-927/SensitiveResultReceiver.qhelp 2023-01-16 14:21:03 +01:00
Michael Nebel
8981d4c06b C#: Add change note. 2023-01-16 13:43:26 +01:00
Michael Nebel
2f602a629f C#: Add upgrade and downgrade scripts. 2023-01-16 13:27:37 +01:00
Erik Krogh Kristensen
8ccc384043 Merge pull request #11858 from erik-krogh/moreSpawn
JS: track shell:true more in js/shell-command-constructed-from-input
2023-01-16 13:24:50 +01:00
Erik Krogh Kristensen
59a8b21851 Merge pull request #10862 from erik-krogh/unsafeCodeConstruction
Rb: Add an `unsafe-code-construction` query
2023-01-16 13:22:58 +01:00
Michael Nebel
3552a41552 C#: Add test case for static abstract and static virtual interface members. 2023-01-16 13:07:50 +01:00
Michael Nebel
dc50b6bad3 C#: Support for operators in implements relations. 2023-01-16 13:07:50 +01:00
Michael Nebel
8c2931cbb8 C#: Operators are now allowed to be declared virtual. 2023-01-16 13:07:50 +01:00
erik-krogh
d072ed969e update clap to 3.0 in QL-for-QL 2023-01-16 12:34:56 +01:00
Paolo Tranquilli
874fe2b8f9 Swift: introduce an in-memory file hash cache
File hashing is now done internally in `SwiftFileInterception` (and
exported as a `getHashOfRealFile` function for future use in linkage
awareness), and using a per-process in-memory cache. The persistent
caching of paths is removed, so the solution is now robust against input
file changes during the build.

For the same reason, the hash to artifact mapping have the symlinks
reversed now. The artifacts themselves are stored using the hash as
filenames, and the original paths of the artifacts are reacreated in the
scratch dir with symlinks mostly for debugging purposes (to understand
what artifact each hash corresponds to, and to follow what was built by
the extractor).
2023-01-16 12:05:36 +01:00
Tony Torralba
fdb3b65bce Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2023-01-16 11:57:37 +01:00
Tony Torralba
7f880a24df Merge pull request #11886 from jelaiw/jelaiw-patch-1
Fix small typo in good/bad code sample.
2023-01-16 09:43:23 +01:00
Paolo Tranquilli
738412260f Merge branch 'main' into redsun82/swift-open-redirection 2023-01-16 09:09:10 +01:00
jelaiw
cf7189bb28 Fix small typo in good/bad code sample. 2023-01-13 19:16:11 -06:00
Geoffrey White
1a416884d4 C++: Do something similar with the other three cases. 2023-01-14 00:09:01 +00:00
Geoffrey White
316117f5c9 C++: Reduce number of regexps. 2023-01-13 18:50:41 +00:00
Geoffrey White
2f09f0e2c1 C++: Turn the huge list into a predicate. 2023-01-13 18:47:18 +00:00
Geoffrey White
13ae15b867 C++: Add tests for more edge cases. 2023-01-13 18:38:29 +00:00
Jami Cogswell
fb6725ddaa Java: add WithoutElement comment for clear methods 2023-01-13 13:20:45 -05:00
Mathias Vorreiter Pedersen
2dbacbc302 Merge pull request #11841 from MathiasVP/swift-add-integral-types
Swift: Add integral type classes
2023-01-13 17:30:57 +00:00
Robert Marsh
601b43ac0a Merge branch 'main' into rdmarsh2/parameterize-range-analysis
Conflicting change to boundedPhiInp copied to RangeAnalysisStage.qll
2023-01-13 12:06:21 -05:00
Geoffrey White
c9a0067705 Swift: Remove flow in cases with multiple variables. 2023-01-13 16:37:23 +00:00
Mathias Vorreiter Pedersen
c5038ed281 Merge pull request #11883 from MathiasVP/fold-definitions
C++: Fix bad join in `definitionOf`
2023-01-13 16:28:26 +00:00
Mathias Vorreiter Pedersen
6e6f2115c0 Merge pull request #11857 from MathiasVP/speedup-missing-check-scanf
C++: Speedup `cpp/missing-check-scanf`
2023-01-13 16:11:16 +00:00
Geoffrey White
2c35af51cd Swift: Move logic into Ssa::WriteDefinition.assigns. 2023-01-13 15:19:33 +00:00
Geoffrey White
8a77906296 Swift: Use Ssa::Definition rather than ConcreteVarDecl. 2023-01-13 15:01:20 +00:00
Michael Nebel
2d46272295 Merge pull request #11881 from michaelnebel/java/modeldiffignore
Java: Ignore missing html artifacts in the Model Diff workflow.
2023-01-13 14:11:19 +01:00
Michael Nebel
b36be009d4 Merge pull request #11834 from michaelnebel/csharp/operators
C# 11: Extractor and library support for Unsigned right shift.
2023-01-13 13:21:02 +01:00
erik-krogh
71af8ab022 simplifications inspired by review 2023-01-13 13:18:52 +01:00
Mathias Vorreiter Pedersen
2283eacc0b C++: Fix bad join in 'definitionOf'. 2023-01-13 11:42:15 +00:00
Mathias Vorreiter Pedersen
59072f9e81 C++: Improve QLDoc. 2023-01-13 11:01:23 +00:00
Mathias Vorreiter Pedersen
dd8bead21a C++: Fix spurious backticks. 2023-01-13 10:57:44 +00:00
Mathias Vorreiter Pedersen
cf9998b932 Merge pull request #5 from geoffw0/integraltypes
Swift: Work on integral type classes
2023-01-13 10:01:23 +00:00
Arthur Baars
5865b51a94 Ruby: build extractor using cross 2023-01-13 10:25:27 +01:00
Arthur Baars
dc6f5f60d1 Ruby: update stats 2023-01-13 10:22:42 +01:00
Arthur Baars
28c9b52dce Ruby: add change note 2023-01-13 10:22:42 +01:00
Arthur Baars
46063c7d04 Ruby: update expected output 2023-01-13 10:22:41 +01:00
Arthur Baars
c4ec674057 Ruby: support anonymous (hash)splat parameters/arguments 2023-01-13 10:22:41 +01:00
Arthur Baars
4d3e2bb814 Ruby: upgrade/downgrade scripts 2023-01-13 10:22:41 +01:00
Arthur Baars
290167e1a3 Ruby: re-generated dbscheme/library 2023-01-13 10:22:41 +01:00
Arthur Baars
3a887d1c92 Ruby: update tree-sitter-{ruby, embedded-template} 2023-01-13 10:22:41 +01:00
Charis Kyriakou
792d4a83f9 Rename VS Code Extension Run Query command 2023-01-13 08:46:35 +00:00
Michael Nebel
600412db48 Java: Ignore missing html artifacts. 2023-01-13 08:58:53 +01:00
Michael Nebel
3b15f2359b Merge pull request #11861 from michaelnebel/java/testmodeldiff
Java: Update the Model Difference workflow to use the `gh api`.
2023-01-13 08:20:18 +01:00
Jami Cogswell
a43f3cf95f Java: remove Supplier.get model 2023-01-12 17:09:13 -05:00
Jami Cogswell
f040ff2d8d Java: undo change to Function.apply test case 2023-01-12 17:01:58 -05:00
Robert Marsh
337a747bde C++: cleanup some unneeded code 2023-01-12 16:38:58 -05:00
Robert Marsh
b2b45237c6 C++: use rounding to prevent float wobble in range analysis 2023-01-12 16:38:57 -05:00
Robert Marsh
31b61b1aa6 C++: fix a join order in range analysis 2023-01-12 16:38:57 -05:00
Robert Marsh
938176c9da C++: update test QL for modulus and sign analysis
These now instantiate their respective parameterized modules. No
results change.
2023-01-12 16:38:56 -05:00
Robert Marsh
7586762b10 C++: fix ambiguous import warnings 2023-01-12 16:38:56 -05:00
Robert Marsh
488368ecde C++: private import for module params 2023-01-12 16:38:55 -05:00
Robert Marsh
23281410e3 C++: Make bounds import private to preserve API 2023-01-12 16:38:54 -05:00
Robert Marsh
6db728190e C++: autoformat 2023-01-12 16:38:36 -05:00
Robert Marsh
02f1957919 C++: make SemBound a RangeAnalysis parameter 2023-01-12 16:38:11 -05:00
Robert Marsh
71b93d125e C++: Make RangeAnalysis.qll expose the old API 2023-01-12 16:38:11 -05:00
Robert Marsh
fb1ef07e9f C++: more parameterized modules in range analysis
This makes the modulus analysis and sign analysis into parameterized
modules which are instantiated in the main range analysis module, and
makes RangeAnalysisSpecific and RangeUtils into parameters to the main
range analysis.
Some classes also need to be moved and made into `instanceof` extensions
because they'd otherwise be extending across parameterized module
boundaries.
2023-01-12 16:38:10 -05:00
Robert Marsh
c062d5e206 C++: move language specific predicates to LangParam 2023-01-12 16:38:10 -05:00
Robert Marsh
c10733f926 C++: fix float binding issue in range analysis 2023-01-12 16:38:09 -05:00
Robert Marsh
b8c43d7a71 C++: convert RangeAnalysis to float 2023-01-12 16:38:09 -05:00
Robert Marsh
eebada46b1 C++: rename to RagneAnalysisStage.qll 2023-01-12 16:38:08 -05:00
Robert Marsh
edbe95837f Convert RangeAnalysis to trivial parameterized mod 2023-01-12 16:38:08 -05:00
Jami Cogswell
c3a1d088ac Java: update change note 2023-01-12 16:32:52 -05:00
Jami Cogswell
a39b2aaaac Java: remove endsWith test case 2023-01-12 16:24:57 -05:00
Jami Cogswell
ffb267937a Java: add endsWith additionalTaintStep to ConditionalBypassFlowConfig 2023-01-12 16:24:05 -05:00
Sarita Iyer
4acd1ababe Update docs/codeql/CONTRIBUTING.MD
Co-authored-by: Felicity Chapman <felicitymay@github.com>
2023-01-12 15:57:43 -05:00
Arthur Baars
af8cb65b2e Merge pull request #11877 from aibaars/ql-ql-cross
QL/Ruby: include OS version in cache keys for Rust binaries
2023-01-12 20:02:25 +01:00
Michael Nebel
fd80974210 Java: Download databases using the gh api instead of lgtm. 2023-01-12 19:30:12 +01:00
Michael Nebel
c1c0ff4308 C#: Update database stats. 2023-01-12 19:06:29 +01:00
Michael Nebel
1384aa669b C#: Add change note. 2023-01-12 19:06:29 +01:00
Michael Nebel
5e89119b3d C#: Add upgrade- and downgrade scripts for unsigned right shift operators. 2023-01-12 19:06:29 +01:00
Michael Nebel
529be7ef18 C++: Sync files. 2023-01-12 19:06:29 +01:00
Michael Nebel
5c466f3319 Java: Sync files and update other relavant files related to the new naming of shift. 2023-01-12 19:06:29 +01:00
Michael Nebel
49a87e152a C#: Add unsigned right shift operator test case. 2023-01-12 19:06:28 +01:00
Michael Nebel
30738103f0 C#: Add unsigned right shift operator class. 2023-01-12 19:06:28 +01:00
Michael Nebel
148dc6de5a C#: Rename shift operator classes. 2023-01-12 19:06:28 +01:00
Michael Nebel
f48eda829f C#: Rename some of the TBinarySignOperation constructors. 2023-01-12 19:06:28 +01:00
Michael Nebel
d92b226041 C#: Add test example for unsigned right shift assignment in intermediate representation. 2023-01-12 19:06:28 +01:00
Michael Nebel
5bb8f8ed5c C#: Support for unsigned shift right in the experimental intermediate representation. 2023-01-12 19:06:28 +01:00
Michael Nebel
f74c7c28ae C#: Auto format test file and update expected test output. 2023-01-12 19:06:28 +01:00
Michael Nebel
0f032c5be9 C#: Sign analysis testcase for unsigned right shift. 2023-01-12 19:06:28 +01:00
Michael Nebel
2568318460 C#: Sign analysis support for unsigned right shift. 2023-01-12 19:06:28 +01:00
Michael Nebel
d06a877709 C#: Introduce test cases and expected result for unsigned right shift. 2023-01-12 19:06:28 +01:00
Michael Nebel
9eb7933778 C#: Implement library support for unsigned right shift. 2023-01-12 19:06:28 +01:00
Michael Nebel
99b7bc3b73 C#: Implement extractor support for unsigned right shift. 2023-01-12 19:06:28 +01:00
Michael Nebel
14c92e6eb3 C#: Add expressions kind including dummy stats for unsigned right shift and unsigned right shift assigment. 2023-01-12 19:06:28 +01:00
Michael Nebel
902b0a60d0 C#: Fixup ShiftExpr rename. 2023-01-12 19:06:28 +01:00
Michael Nebel
36980bbf42 C#: Rename shift expression classes. 2023-01-12 19:06:27 +01:00
Michael Nebel
a9f1c95513 C#: Rename shift assignment expression classes. 2023-01-12 19:06:27 +01:00
Chris Smowton
8aa2c23ba8 Merge pull request #11700 from JLLeitschuh/doc/JLL/improve-java-unsafe-deserialization-documentation
[Java] Document fixes for deserialization vulnerabilities by framework
2023-01-12 18:04:13 +00:00
Chris Smowton
09d8a50494 Spelling 2023-01-12 17:46:00 +00:00
Michael Nebel
aefb43324b Merge pull request #11738 from michaelnebel/go/maddataextensions
Go: Models as Data using extensions.
2023-01-12 18:42:35 +01:00
Erik Krogh Kristensen
8f9ad1f5ba Merge pull request #11872 from erik-krogh/jsAst
JS: Fixup some problems in PrintAST
2023-01-12 16:56:56 +01:00
Geoffrey White
7f31c9c7e5 Swift: Add a test. 2023-01-12 15:19:57 +00:00
Jami Cogswell
e0444449c8 Java: remove Function.apply model 2023-01-12 09:58:53 -05:00
Arthur Baars
e29e077a03 Ruby/QL4QL: include OS version in cache keys 2023-01-12 15:47:10 +01:00
erik-krogh
7ae27bcc34 fix errors in JS printAst 2023-01-12 15:37:52 +01:00
Henry Mercer
15ead6d0e6 Merge pull request #11864 from github/codeql-ci/atm/release-0.4.5
JS: Bump version numbers of ML-powered packs after 0.4.5 release
2023-01-12 13:51:24 +00:00
Jami
c725c447ac Merge branch 'main' into jcogs33/update-paramsString 2023-01-12 08:24:57 -05:00
Henry Mercer
70f1015fba Merge branch 'main' into codeql-ci/atm/release-0.4.5 2023-01-12 12:32:25 +00:00
Ian Lynagh
9ebe59d353 Merge pull request #11637 from igfoo/igfoo/kotlin-1.8
Kotlin: Add 1.8 support
2023-01-12 12:15:00 +00:00
Geoffrey White
3d1b2fdbda Swift: Rename NumericOrCharType.qll -> Numer> NumericType.qll. 2023-01-12 11:46:51 +00:00
Joe Farebrother
e12febfd96 Add change note 2023-01-12 11:44:39 +00:00
Joe Farebrother
b565f997a0 Improve qhelp 2023-01-12 11:44:39 +00:00
Joe Farebrother
639c42c9e9 Fix qhelp errors and ql-for-ql errors 2023-01-12 11:44:39 +00:00
Joe Farebrother
f52db7f9a3 Add qhelp 2023-01-12 11:44:39 +00:00
Joe Farebrother
a88759283a Fix typo in qldoc 2023-01-12 11:44:39 +00:00
Joe Farebrother
7e7b5b4488 Improve test case 2023-01-12 11:44:39 +00:00
Joe Farebrother
8449dabefe Add qldoc 2023-01-12 11:44:39 +00:00
Joe Farebrother
de565f9ccc Add test and fix a bug 2023-01-12 11:44:39 +00:00
Joe Farebrother
b96edb9c64 Add Sensitive Result Receiver query 2023-01-12 11:44:39 +00:00
Geoffrey White
418d593a97 Swift: Replace NumericOrCharType with a more basic NumericType, and rename classes for consistency with other static languages. 2023-01-12 11:43:20 +00:00
Geoffrey White
d0eb167d47 Swift: Merge FloatingPointType.qll into NumericOrCharType.qll, because it is a numeric type and other stuff like CharacterType is there. 2023-01-12 11:42:36 +00:00
Geoffrey White
4e5483744f Swift: Add a test case we're discussing. 2023-01-12 10:52:03 +00:00
Michael Nebel
48d0eccbf6 Go: Cleanup and renaming. 2023-01-12 11:13:34 +01:00
Michael Nebel
3749a1bd4d Go: Migrate unit tests to use data extensions for Models as Data. 2023-01-12 11:13:33 +01:00
Michael Nebel
218f553fef Go: Convert remaining CSV production models to use data extensions. 2023-01-12 11:13:33 +01:00
Michael Nebel
ebb3485a73 Go: Use the extensible predicates for model definitions. 2023-01-12 11:13:33 +01:00
Michael Nebel
5fd687d3df Go: Add MaD related extensible predicates. 2023-01-12 11:13:33 +01:00
Michael Nebel
0f993a0d26 Go: Prepare library for adding extensions. 2023-01-12 11:13:28 +01:00
Mathias Vorreiter Pedersen
1ae52b6c7e C++: Speedup 'MissingCheckScanf'. 2023-01-12 10:13:02 +00:00
Paolo Tranquilli
4f5f0aad45 Merge branch 'main' into redsun82/swift-open-redirection 2023-01-12 10:54:04 +01:00
Michael Nebel
18a815ca8b Merge pull request #11721 from michaelnebel/csharpjava/refactorprovenance
C#/Java: Re-factor provenance related predicates.
2023-01-12 10:50:31 +01:00
yoff
006eaf3e2a Merge pull request #11088 from yoff/python/inline-query-tests
Python: Inline query tests
2023-01-12 10:32:26 +01:00
Geoffrey White
994ea704da Swift: Clean up the QL a little. 2023-01-12 09:31:48 +00:00
Jami Cogswell
fd593fd4f0 Java: undo changes to tests that were affected by numeric-flow summary models 2023-01-11 22:34:19 -05:00
Harry Maclean
33a1469a56 Ruby: Add change note 2023-01-12 16:29:00 +13:00
Jami Cogswell
ce74c9d959 Java: Date models as neutral 2023-01-11 22:15:41 -05:00
Jami Cogswell
6bb865ad05 Java: make numeric flow models neutral 2023-01-11 18:04:43 -05:00
Henning Makholm
1d4b2fd0bb Merge pull request #11870 from github/hmakholm/pr/mergeback-2.12.0
Merge codeql-cli-2.12.0 back to main
2023-01-11 23:51:56 +01:00
Harry Maclean
8219465389 Ruby: fix missing doc 2023-01-12 11:35:35 +13:00
Harry Maclean
0626d693f5 Ruby: Recognise rack applications
This is a basic first step in modelling rack apps. We recognise classes
that look like rack applications and then treat the argument to `call`
in the same way that we treat `request.env` in ActionController classes.

This finds a TP in CVE-2021-43840.
2023-01-12 11:28:31 +13:00
Pierre
4e1f772f23 Merge pull request #11702 from github/turbo/experimental/combined
Introduce the security-experimental CodeQL suite and experimental tag
2023-01-11 20:37:42 +01:00
Geoffrey White
6a0b56bf40 Swift: Fix for extensions. 2023-01-11 18:32:07 +00:00
Geoffrey White
2622de9747 Swift: Improve Core Data coverage. 2023-01-11 18:26:34 +00:00
Geoffrey White
82f9903bf0 Swift: Additional test cases for swift/cleartext-storage-database on Core Data. 2023-01-11 18:22:32 +00:00
Jami Cogswell
0c7ffb0554 Java: update System.getProperty model 2023-01-11 12:04:22 -05:00
Pierre
c3116b3f0f Merge branch 'main' into turbo/experimental/combined 2023-01-11 18:02:55 +01:00
Jami Cogswell
2a99af0e6d Java: remove summary model for String.endsWith 2023-01-11 10:58:46 -05:00
Jami Cogswell
99ee6c95a1 Java: remove models for Consumer.accept and Collectors.toMap 2023-01-11 10:44:38 -05:00
Jami Cogswell
ac064ac2a7 Java: remove model for Collectors.joining 2023-01-11 10:30:49 -05:00
Michael Nebel
7e4f7a0c17 C#: Address review comments and sync files. 2023-01-11 16:29:24 +01:00
Michael Nebel
67cbe38255 Sync files. 2023-01-11 16:20:55 +01:00
Michael Nebel
8112058a0a Java: Adapt TopJdpApi library to the re-factor. 2023-01-11 16:20:55 +01:00
Michael Nebel
372ecf402f Go: Delete unused summaryModel predicate. 2023-01-11 16:20:55 +01:00
Michael Nebel
80a4197604 Swift: Re-factor provenance related predicates for summarized callable. 2023-01-11 16:20:55 +01:00
Michael Nebel
c01361a1fd Ruby: Re-factor provenance related predicates for summarized callable. 2023-01-11 16:20:55 +01:00
Michael Nebel
59a9e255c7 Python: Re-factor provenance related predicates for summarized callable. 2023-01-11 16:20:55 +01:00
Michael Nebel
6622eda04c Go: Re-factor provenance related predicates for summarized callable. 2023-01-11 16:20:55 +01:00
Michael Nebel
6a047d6916 Java: Re-factor provenance related predicates for summarized callable. 2023-01-11 16:20:55 +01:00
Michael Nebel
ea173f9516 Sync files. 2023-01-11 16:20:55 +01:00
Michael Nebel
7422029e49 C#: Re-factor provenance related predicates for summarized callable. 2023-01-11 16:20:48 +01:00
Michael Nebel
4b47b08ed2 Merge pull request #11760 from michaelnebel/movemodelgenerator
C#/Java: Move the modelgenerator.
2023-01-11 16:02:36 +01:00
Tony Torralba
c6d9e1ec81 Merge pull request #11742 from atorralba/atorralba/swift/more-path-injection-sinks
Swift: Add more path injection sinks
2023-01-11 15:15:42 +01:00
Tony Torralba
c115a9fee4 Add more path injection sinks 2023-01-11 14:28:24 +01:00
Tony Torralba
5d54482c71 Merge pull request #11770 from atorralba/atorralba/ql/omittable-exists
QL: Add OmittableExists query
2023-01-11 14:27:40 +01:00
Michael Nebel
11ca3f49f6 C#/Java: Adjust imports after moving files. 2023-01-11 13:13:33 +01:00
Michael Nebel
787b4743ee C#/Java: Rename the directories containing the model generator and tests. 2023-01-11 13:13:33 +01:00
Michael Nebel
178fd0e9e1 C#/Java: Remove all dashes in mode-generator. 2023-01-11 13:13:33 +01:00
erik-krogh
6914e9a17a Merge branch 'main' into atorralba/ql/omittable-exists 2023-01-11 13:09:38 +01:00
Erik Krogh Kristensen
466f24663e Merge pull request #11867 from erik-krogh/qlFix
QL: move queries folder instead of .cache folder now that we got .qlx
2023-01-11 13:03:47 +01:00
Erik Krogh Kristensen
3fa6a7cbff cache -> queries
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2023-01-11 12:29:15 +01:00
Tony Torralba
a4f813183e Merge pull request #11785 from atorralba/atorralba/swift/grdb-sinks
Swift: Add sinks for the GRDB library
2023-01-11 11:49:37 +01:00
erik-krogh
74a58f64aa move queries folder instead of .cache folder now that we got .qlx 2023-01-11 11:13:42 +01:00
erik-krogh
ed2dd87bda update the codeql-action version used in QL-for-QL 2023-01-11 11:13:06 +01:00
Tony Torralba
ecf568629b Add ExprAggregate as a negative edge in getConjunctionParentRec 2023-01-11 09:41:16 +01:00
Jami Cogswell
181a711f04 Java: switch Collectors.joining model from neutral to summary 2023-01-10 21:06:03 -05:00
github-actions[bot]
76e121e359 JS: Bump version of ML-powered library and query packs to 0.4.6 2023-01-10 21:11:23 +00:00
github-actions[bot]
dc88bdccc7 JS: Bump patch version of ML-powered library and query packs 2023-01-10 21:04:31 +00:00
Jami Cogswell
faae811be7 Java: try simplification of paramsString and paramsStringPart 2023-01-10 13:35:52 -05:00
Jami Cogswell
65aa064838 Java: update paramsString qldoc 2023-01-10 13:33:47 -05:00
Edward Minnix III
ce06df3152 Merge pull request #11628 from egregius313/egregius313/android-webview-addjavascriptinterface-dataflow
Java: Add parameters of methods annotated @JavascriptInterface as remote flow sources
2023-01-10 12:41:52 -05:00
erik-krogh
38ca68febb recognize "-->" as a bad tag filter 2023-01-10 18:09:56 +01:00
Florin Coada
4c1c12dd70 suggestions in list format 2023-01-10 11:18:56 -05:00
Jonathan Leitschuh
1d7881e03f Apply suggestions from code review
Co-authored-by: Chris Smowton <smowton@github.com>
2023-01-10 11:18:56 -05:00
Tony Torralba
b7364f5428 Update UnsafeDeserialization.qhelp
Move the table under <recommendation>, minor fixes.
2023-01-10 11:18:56 -05:00
Jonathan Leitschuh
3fa11c21c3 [Java] Document fixes for deserialization vulnerabilities by framework
Related https://github.com/github/codeql/issues/11603
2023-01-10 11:18:56 -05:00
Paolo Tranquilli
0ad585cfe6 Merge pull request #11860 from github/redsun82/swift-clang-14
Swift: make compilation with newer STL possible
2023-01-10 17:17:56 +01:00
Erik Krogh Kristensen
54c780bdf9 Merge pull request #11853 from erik-krogh/assignMore
JS: add local flow when recognizing Object.assign calls for library-inputs
2023-01-10 17:04:29 +01:00
Tony Torralba
ae8c75ac97 Generalize ConjunctionParent 2023-01-10 16:08:42 +01:00
Tony Torralba
72a11e737d Merge pull request #11775 from atorralba/atorralba/all/omittable-exists
All: Remove omittable exists variables
2023-01-10 16:07:06 +01:00
Ian Lynagh
3367da82c4 Kotlin: Accept test changes
We get better locations with Kotlin 1.8.0.
2023-01-10 14:41:30 +00:00
Ian Lynagh
b7eb521fa0 Kotlin: Fix custom_plugin test for Kotlin 1.8.0 2023-01-10 14:41:30 +00:00
Ian Lynagh
c71ea80029 Kotlin: Accept test changes
We now get better locations, with Kotlin 1.8.0.
2023-01-10 14:41:30 +00:00
Ian Lynagh
20b35e5d02 Kotlin: 1.8.0 changes 2023-01-10 14:41:30 +00:00
Ian Lynagh
c4119761cc Kotlin: Another 1.8 build fix 2023-01-10 14:41:30 +00:00
Ian Lynagh
89b3363761 Kotlin: Bump CI version to 1.8.0-Beta 2023-01-10 14:41:30 +00:00
Ian Lynagh
b51c3aae85 Kotlin: Logs test: Allow for -Beta versions etc when parsing the logs 2023-01-10 14:41:29 +00:00
Ian Lynagh
6fbda1a9f0 Kotlin: Accept test changes with 1.8 2023-01-10 14:41:29 +00:00
Ian Lynagh
f7d8d16ed3 Kotlin: Fix build for 1.8.0-Beta
The build no longer works for Kotlin < 1.8: We get

    error: class 'org.jetbrains.kotlin.ir.IrElement' was compiled
           with an incompatible version of Kotlin. The binary version
           of its metadata is 1.8.0, expected version is 1.6.0.
2023-01-10 14:41:29 +00:00
erik-krogh
62b69bbd3e autoformat 2023-01-10 15:38:13 +01:00
Erik Krogh Kristensen
6623e5fbf3 Merge pull request #11852 from erik-krogh/jsInfiniteChar
JS: recognize an infinite repetition of a char-class like regex as a char-class like regex
2023-01-10 15:32:22 +01:00
Erik Krogh Kristensen
ce8836fb65 Update javascript/ql/lib/semmle/javascript/PackageExports.qll
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
2023-01-10 15:30:44 +01:00
erik-krogh
43696f5e27 add explicit this 2023-01-10 15:27:37 +01:00
erik-krogh
23a847b1cf track shell:true more in js/shell-command-constructed-from-input 2023-01-10 15:27:37 +01:00
Erik Krogh Kristensen
9f8d10de11 Merge pull request #11851 from erik-krogh/jsFixMissingThis
JS: fix bad join-order in js/missing-this-qualifier
2023-01-10 15:23:25 +01:00
Paolo Tranquilli
2fb5621527 Swift: replace $(CC) with clang
On macOS `$(CC)` points to a wrapper that requires `DEVELOPER_DIR` to be
set in the environment. Using `clang` is slightly less generic, but
that's our default any way. Even if we do set a different clang version
somewhere, the selected version of GCC would not change, and the test
is targeting that.
2023-01-10 14:58:21 +01:00
Paolo Tranquilli
943763a026 Swift: add -Wno-pragma-once-outside-header to check 2023-01-10 14:30:35 +01:00
Paolo Tranquilli
28d79eeb77 Swift: make compilation with different STL versions possible
Previous to this patch the code contained a workaround for the standard
defect

https://cplusplus.github.io/LWG/issue3657

where `std::filesystem::path` did not have a `std::hash` implementation.

This patch allows compiling against versions of the STL that contain the
fix to the above issue. This is done by running the compiler against
code defining `std::hash<std::filesystem::path>`: if compilation
succeeds, it means the fix is not there and we need to use the
workaround, contained in `PathHash.h.workaround`. Otherwise, the fix is
there and we use `PathHash.h.fixed` instead, which only includes the
standard headers included by `PathHash.h.workaround`, so that one is a
drop-in replacement of the other.
2023-01-10 14:14:33 +01:00
Jeroen Ketema
1a4048d238 Merge pull request #11830 from jketema/frontend-update
C++: Changes for frontend update
2023-01-10 14:01:46 +01:00
erik-krogh
5c388c554c fix that the TypeTracker was unrestricted for the base-case of nonFirstLocationType 2023-01-10 13:39:50 +01:00
erik-krogh
e02b67af63 add failing test 2023-01-10 13:39:50 +01:00
Tony Torralba
50cd40ed20 Swift: Remove omittable exists variables 2023-01-10 13:39:50 +01:00
Tony Torralba
7ef8099a8b Shared: Remove omittable exists variables 2023-01-10 13:39:50 +01:00
Tony Torralba
c9d1cd97fb Ruby: Remove omittable exists variables 2023-01-10 13:39:49 +01:00
Tony Torralba
f6c3f77602 QL: Remove omittable exists variables 2023-01-10 13:37:58 +01:00
Tony Torralba
d87c8c75d6 Python: Remove omittable exists variables 2023-01-10 13:37:35 +01:00
Tony Torralba
3b6dae41cd JavaScript: Remove omittable exists variables 2023-01-10 13:37:21 +01:00
Tony Torralba
32471d326e Java: Remove omittable exists variables 2023-01-10 13:37:19 +01:00
Tony Torralba
7a92970d89 Go: Remove omittable exists variables 2023-01-10 13:36:48 +01:00
Tony Torralba
2ca0df0369 C#: Remove omittable exists variables 2023-01-10 13:36:25 +01:00
Tony Torralba
3fcc99e5cb C++: Remove omittable exists variables 2023-01-10 13:36:01 +01:00
Erik Krogh Kristensen
f2658a0936 apply suggestions from doc review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2023-01-10 12:56:22 +01:00
erik-krogh
79e161e046 slightly broaden the regular expression that recognizes bad string-concats used as shell commands 2023-01-10 12:49:37 +01:00
Tony Torralba
da90ae0e8f Update java/ql/lib/semmle/code/java/dataflow/FlowSources.qll 2023-01-10 11:18:53 +01:00
Jeroen Ketema
8d46642de3 C++: Update dbscheme stats file 2023-01-10 10:41:43 +01:00
Jeroen Ketema
2fc6484162 C++: Add dbscheme upgrade and downgrade scripts 2023-01-10 10:41:43 +01:00
Jeroen Ketema
1bab950023 C++: Introduce (_Complex) _Float16 type which is needed after frontend update 2023-01-10 10:41:43 +01:00
Jeroen Ketema
282ca1094e C++: Accept test changes after improving size of _Float128 in frontend 2023-01-10 10:41:43 +01:00
Jeroen Ketema
e215c4c94c C++: Accept test changes after frontend update
The location of a reference dereference has changed slightly.
2023-01-10 10:41:43 +01:00
Michael Nebel
16cd148961 Merge pull request #11711 from michaelnebel/externalflowcleanup
C#/Java: Delete deprecated ModelCsv classes and related predicates.
2023-01-10 10:22:50 +01:00
Michael Nebel
1729319ebe Merge pull request #11804 from michaelnebel/csharp/alignqueryids
C#: Align query IDs.
2023-01-10 10:14:07 +01:00
Michael Nebel
18a0abdb4c Merge pull request #11740 from michaelnebel/csharp/updatestats
C#: Update stats based on projects.
2023-01-10 10:09:53 +01:00
Ed Minnix
293a203756 Move JavascriptInterfaceMethod to WebView.qll 2023-01-09 15:10:23 -05:00
Rasmus Lerchedahl Petersen
2edbfbf8bc python: update test expectations
...now the bug is fixed
2023-01-09 20:35:20 +01:00
Mathias Vorreiter Pedersen
7f5344e025 Update swift/ql/lib/codeql/swift/elements/type/NumericOrCharType.qll
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2023-01-09 17:08:27 +00:00
Tony Torralba
8e0a018673 Consider Int8 and UInt8 as OsLogNonRedactedTypes 2023-01-09 18:05:18 +01:00
Tony Torralba
49a41c98ee Test that hashed passwords are 'safe' to log
This doesn't seem completely right, but the heuristic approach we have regarding sensitive expressions has to draw the line somewhere.
2023-01-09 18:01:07 +01:00
Tony Torralba
160d89fb4e Add qhelp examples 2023-01-09 18:01:07 +01:00
Tony Torralba
33029b0ed8 Fix sanitizer QLDoc 2023-01-09 18:01:07 +01:00
Tony Torralba
7e0869965c Uncomment tests 2023-01-09 18:01:07 +01:00
Tony Torralba
c1f19dd145 Add stub so that tests work on Linux 2023-01-09 18:01:07 +01:00
Tony Torralba
b203a9eb6e Add a sanitizer for OSLogPrivacy options
Add test cases to verify how the sanitizer behaves depending on the argument type and the privacy option being used.
2023-01-09 18:01:07 +01:00
Tony Torralba
aad56097ac Add Cleartext Loggin query for Swift.
With some caveats: see TODO comments and failing tests.
2023-01-09 18:01:07 +01:00
Rasmus Lerchedahl Petersen
c142495a8b python: simplify code 2023-01-09 17:51:45 +01:00
Rasmus Lerchedahl Petersen
5fe62e293a python: fix bug, add clarifying comment 2023-01-09 17:45:50 +01:00
erik-krogh
9f100ef2c6 add local flow when recognizing Object.assign calls for library-inputs 2023-01-09 17:44:11 +01:00
Tony Torralba
eb78661c1f Add missing SQL injection tests for the GRDB SQL class 2023-01-09 17:36:54 +01:00
erik-krogh
90f9e3f825 recognize an infinite repetition of a char-class like regex as a char-class like regex 2023-01-09 17:25:08 +01:00
Sarita Iyer
be06469a19 Merge pull request #11835 from github/saritai/pr/qlx
Docs: CodeQL pack compatibility
2023-01-09 10:15:08 -05:00
Ed Minnix
909b1d70d9 Rename files to say "Allow" instead of "Permit" 2023-01-09 10:11:03 -05:00
Ed Minnix
c723df3ca7 Fix alert message in expected file 2023-01-09 10:08:19 -05:00
erik-krogh
785c21f462 fix bad join-order in js/missing-this-qualifier 2023-01-09 16:06:26 +01:00
Ed Minnix
f626d4794a Change wording from "permit" to "allow" in id and name 2023-01-09 10:03:12 -05:00
Ed Minnix
972b4629c8 Fix typo in change note 2023-01-09 10:01:38 -05:00
Ed Minnix
64668883a4 Add good example to documentation 2023-01-09 09:59:38 -05:00
Ed Minnix
2ec73c50f9 Mention WebView in alert message 2023-01-09 09:55:09 -05:00
Arthur Baars
664fdc3b2a Merge pull request #11815 from aibaars/too-many-fields
Ruby: use record_parse_error_for_node to report extractor error
2023-01-09 15:40:19 +01:00
Erik Krogh Kristensen
5157d4df7b Merge pull request #11581 from erik-krogh/stdin
Rb: add stdin as source for unsafe-deserialization
2023-01-09 13:57:47 +01:00
Chris Smowton
e9bbb5d7fa Merge pull request #11730 from smowton/smowton/admin/improve-sql-unescaped-docs
Java: improve naming and description of SqlUnescaped.ql
2023-01-09 12:50:27 +00:00
yoff
c01ce955ba Merge pull request #11778 from yoff/shared/inline-tests
Shared: Inline test expectations
2023-01-09 13:21:18 +01:00
Chris Smowton
2e26fb1171 Merge pull request #11819 from smowton/smowton/admin/port-java-autobuilder-tests
Add Java autobuilder integration tests
2023-01-09 12:17:39 +00:00
Chris Smowton
efe23c1da7 Note that alerts should not be re-raised 2023-01-09 10:56:13 +00:00
Chris Smowton
994a46289f Add change note 2023-01-09 10:56:13 +00:00
Chris Smowton
ef27f9fe96 Replace one more mention of escaping 2023-01-09 10:56:13 +00:00
Chris Smowton
45c732a6f9 Java: improve naming and description of SqlUnescaped.ql
Since the main thing it's objecting to is concatenation not lack of escaping (in particular it doesn't look for escaping sanitizers), rename and re-describe it accordingly.
2023-01-09 10:56:13 +00:00
Mathias Vorreiter Pedersen
381301e552 Update swift/ql/lib/swift.qll
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2023-01-09 10:32:52 +00:00
Geoffrey White
9333e80def Swift: Add getVaList stub to the test. 2023-01-09 10:29:37 +00:00
Taus
06ea249997 Merge pull request #11820 from yoff/python/fix-downgrades
Python: fix downgrade script
2023-01-09 11:24:41 +01:00
Mathias Vorreiter Pedersen
6bb09ef289 Swift: Add integral type classes. 2023-01-09 09:43:09 +00:00
Mathias Vorreiter Pedersen
9be9636816 Merge pull request #11670 from atorralba/atorralba/swift/predicate-injection
Swift: Add predicate injection query
2023-01-09 08:54:13 +00:00
erik-krogh
d67e756f42 make the import of Gem private 2023-01-09 09:13:01 +01:00
Harry Maclean
5b117084db Merge pull request #11534 from hmac/array-inclusion-barrier-guard-constant
Ruby: Make array inclusion barrier more sensitive
2023-01-09 20:57:09 +13:00
Paolo Tranquilli
82d9edfabf Merge branch 'main' into redsun82/swift-open-redirection 2023-01-09 08:44:02 +01:00
Sarita Iyer
f15291a9de Change the order of sections 2023-01-06 15:00:43 -05:00
Sarita Iyer
d079c7a5ef Apply suggestions from code review
Co-authored-by: Felicity Chapman <felicitymay@github.com>
2023-01-06 14:57:24 -05:00
Jami Cogswell
a3c7b2c3a2 Java: move java.lang.Math.min to the correct file 2023-01-06 14:35:09 -05:00
Geoffrey White
bb50a99b36 Swift: Additional test cases. 2023-01-06 18:48:46 +00:00
Geoffrey White
b5dd815249 Swift: Flow through optional binding. 2023-01-06 18:34:22 +00:00
Geoffrey White
c598d9b882 Swift: Generalize an SSA case for variables declared in Patterns. 2023-01-06 18:34:22 +00:00
Geoffrey White
8a9a69fa00 Swift: Add more dataflow tests for of optionals, patterns, enums. 2023-01-06 18:34:22 +00:00
Jeroen Ketema
a743fbcc95 Merge pull request #11799 from jketema/case-uncomment
C++: Uncomment cases in dbscheme
2023-01-06 19:26:53 +01:00
Sarita Iyer
d7bf2d9375 docs for codeql pack compatibility 2023-01-06 12:07:24 -05:00
Geoffrey White
04f87a26a9 Swift: Test layout change. 2023-01-06 16:52:54 +00:00
Sarita Iyer
a9867a266e fixed link 2023-01-06 11:50:07 -05:00
Sarita Iyer
d68cfc7d4f codeql pack compatibility docs 2023-01-06 11:17:02 -05:00
erik-krogh
538adb47a3 update expected output for DuplicateCharacterInSet 2023-01-06 15:41:57 +01:00
Chris Smowton
831255e9c0 Merge pull request #11832 from github/mbg/fix/go-version-warnings
Go: Handle output from `go version` more gracefully
2023-01-06 14:05:39 +00:00
Jeroen Ketema
c1bc097355 C++: Add upgrade/downgrade scripts for dbscheme update 2023-01-06 14:26:24 +01:00
Jeroen Ketema
cdb34bb1f9 C++: Update database stats file 2023-01-06 14:26:23 +01:00
Jeroen Ketema
b9b0c8091f C++: Uncomment cases in dbscheme
Note that the builtin types `__int{8,16,32,64}` are not uncommented,
as these are never and could have never been generated by the
extractor.
2023-01-06 14:26:23 +01:00
Geoffrey White
f3914ffe25 Merge pull request #11823 from geoffw0/heuristicalloc
C++: Use HeuristicAllocationExpr in more queries
2023-01-06 13:13:14 +00:00
Jami
f5e5f6dfd1 Merge pull request #11821 from jcogs33/jcogs33/fix-mad-typos
Java: fix typos in MaD row `name` columns for `MappingSqlQuery` and `MappingSqlQueryWithParameters`
2023-01-06 07:59:30 -05:00
Rasmus Lerchedahl Petersen
03bd6cb414 python: Allow optional result=OK
Also add a further test case
2023-01-06 13:33:12 +01:00
erik-krogh
10308f5875 track string-constants to regular expression uses 2023-01-06 13:17:31 +01:00
Nick Rolfe
4c5f149afd Merge pull request #11831 from github/post-release-prep/codeql-cli-2.12.0
Post-release preparation for codeql-cli-2.12.0
2023-01-06 12:15:17 +00:00
Michael B. Gale
1ef1d63c11 Add test for parseGoVersion 2023-01-06 11:20:51 +00:00
Michael B. Gale
9af9b32722 Find the last line of output from go version 2023-01-06 11:20:39 +00:00
Geoffrey White
bb451f3911 C++: Fix result duplication. 2023-01-06 11:05:47 +00:00
github-actions[bot]
cdb8f67601 Post-release preparation for codeql-cli-2.12.0 2023-01-06 10:36:34 +00:00
Rasmus Lerchedahl Petersen
8d9e94a00f swift: fix typo 2023-01-06 11:22:49 +01:00
erik-krogh
0a1769657d add change-note 2023-01-06 09:09:09 +01:00
erik-krogh
19d2b49562 drive-by: make Base64.decode64(..) into a flowsummary that is shared with all queries 2023-01-06 09:04:37 +01:00
erik-krogh
1a27441cfb drive-by: delete code-execution sinks from unsafe-deserialization, we risked duplicate alerts 2023-01-06 09:04:36 +01:00
erik-krogh
0e6028a7f3 add stdin as source for unsafe-deserialization 2023-01-06 09:04:36 +01:00
Rasmus Lerchedahl Petersen
d42bb119fe python: align annotations with Ruby
use `result=BAD` for expected alert
and `result=OK` on sinks where alerts are not wanted.
2023-01-05 21:41:28 +01:00
Rasmus Lerchedahl Petersen
ad95225272 python: improve code
according to alert and reviewer's suggestion
2023-01-05 20:42:29 +01:00
erik-krogh
f98ff65b11 use eval() instead of send() in test 2023-01-05 20:04:04 +01:00
Erik Krogh Kristensen
d9176541c6 Apply suggestions from code review
Co-authored-by: Alex Ford <alexrford@users.noreply.github.com>
2023-01-05 20:02:54 +01:00
Nick Rolfe
44213f0144 Merge pull request #11826 from github/nickrolfe/check-change-note
CI: fail if a changenote filename doesn't have the right format
2023-01-05 16:55:30 +00:00
Nick Rolfe
4e6baf83c8 Update .github/workflows/check-change-note.yml
Co-authored-by: Taus <tausbn@github.com>
2023-01-05 16:26:43 +00:00
Nick Rolfe
0beca9d96c CI: fail if a changenote filename doesn't have the right format 2023-01-05 16:01:07 +00:00
Jeroen Ketema
f370cd840c Merge pull request #11818 from jketema/downgrade-fix
C++: Fix the expression kind in two of the downgrade scripts
2023-01-05 16:33:16 +01:00
Geoffrey White
b3e82498fa C++: Change note. 2023-01-05 15:06:40 +00:00
Jami Cogswell
f03f687d61 Java: add change note 2023-01-05 09:08:04 -05:00
Rasmus Lerchedahl Petersen
bb26c31f84 Python: fix downgrade script
When new kinds are inserted, new indices exists that do not
correspond to any old indices.
These were previously mapped, now they are not.
2023-01-05 14:56:52 +01:00
Jami Cogswell
0640bd9d8b Java: fix typos in the MaD row name columns for MappingSqlQuery and MappingSqlQueryWithParameters 2023-01-05 08:32:22 -05:00
Rasmus Lerchedahl Petersen
8afb541718 cpp/swift: fix qldoc 2023-01-05 14:30:13 +01:00
yoff
a74062cd51 Update go/ql/test/TestUtilities/InlineExpectationsTest.qll
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2023-01-05 14:12:16 +01:00
Geoffrey White
3b31da8a62 C++: Update the experimental query as well. 2023-01-05 12:48:17 +00:00
Geoffrey White
46baf9d5e5 C++: Add test cases for an experimental query as well. 2023-01-05 12:48:16 +00:00
Geoffrey White
c160e0b2a4 C++: Add a warning on HeuristicAllocationExpr.getSizeBytes() and similar methods. 2023-01-05 12:47:52 +00:00
Geoffrey White
823c767aac C++: Undo changes to SizeCheck.ql, SizeCheck2.ql. 2023-01-05 12:34:12 +00:00
Chris Smowton
52297c0b23 Add Java autobuilder integration tests 2023-01-05 12:19:25 +00:00
Jonas Jensen
c8f35ea1ea Merge pull request #11810 from kaspersv/kaspersv/inline-late-pragma
Add inline_late pragma to QL language spec
2023-01-05 13:15:12 +01:00
Geoffrey White
2023abdc60 C++: Update the queries. 2023-01-05 11:33:58 +00:00
Geoffrey White
a9aa67177b C++: Add test cases for HeuristicAllocationExpr in queries. 2023-01-05 11:30:21 +00:00
Geoffrey White
10ca2dac19 C++: Remove unnecessary 'semmle' directory. 2023-01-05 11:30:15 +00:00
Jeroen Ketema
14283f01ac C++: Fix the expression kind in two of the downgrade scripts
A 0 value for the expression kind is not valid, as 0 does not occur in the
relevant case split. This should have been the value of `@errorexpr`, which
is 1.
2023-01-05 11:04:31 +01:00
Rasmus Lerchedahl Petersen
c3b3c05cf3 Revert "Merge pull request #37 from erik-krogh/shared/inline-tests"
This reverts commit 65fe9abcfe, reversing
changes made to 08e9d3391f.
2023-01-05 09:19:43 +01:00
Sarita Iyer
745d30252c Update CONTRIBUTING.MD 2023-01-04 16:49:27 -05:00
Sarita Iyer
a62a8d9960 Update CONTRIBUTING.MD 2023-01-04 16:47:34 -05:00
Sarita Iyer
d859e1e9a3 add contributing info 2023-01-04 16:43:17 -05:00
Rasmus Lerchedahl Petersen
2e46919e10 java: nicer code as suggested by review 2023-01-04 19:50:29 +01:00
Geoffrey White
e45750a8ca Merge branch 'main' into format 2023-01-04 18:00:59 +00:00
Arthur Baars
799e0c1bcc Ruby: use record_parse_error_for_node to report extractor error 2023-01-04 17:35:47 +01:00
yoff
65fe9abcfe Merge pull request #37 from erik-krogh/shared/inline-tests
inline Location into the shared implementation of InlineExpectationsTest
2023-01-04 17:08:23 +01:00
Kasper Svendsen
9ad572fa29 Add inline_late pragma to QL language spec 2023-01-04 11:28:08 +01:00
Harry Maclean
4d228bcddf Ruby: Recognise more string-valued variables
This increases the sensitivity of our barrier guards.
2023-01-04 11:45:10 +13:00
Harry Maclean
9944252c43 Ruby: Add test for barrier guards
This demonstrates that we are missing a guard when a case branch
compares against a string-valued variable rather than a string literal.
2023-01-04 11:45:10 +13:00
Harry Maclean
698a679c78 Ruby: add test 2023-01-04 11:45:10 +13:00
Harry Maclean
0fbb6bf608 Ruby: Make array inclusion barrier more sensitive 2023-01-04 11:45:09 +13:00
Jami Cogswell
abe501c1af Java: add change note 2023-01-03 17:15:50 -05:00
Jami Cogswell
5d92792e40 Java: update test case affected by Function.apply model 2023-01-03 16:14:08 -05:00
Jami Cogswell
feaae16f7c Java: adjust comments 2023-01-03 16:08:14 -05:00
Ed Minnix
0be8648a9d Add changenote 2023-01-03 15:55:53 -05:00
Ed Minnix
28f555c2b2 Add simple test case for @JavascriptInterface parameter flow 2023-01-03 15:31:40 -05:00
Ed Minnix
ab7ca1d642 Java: Add parameters of @JavascriptInterface methods as a remote flow sources 2023-01-03 15:31:40 -05:00
Ed Minnix
f9b8200009 Add stub for android.webkit.JavascriptInterface annoation 2023-01-03 15:31:40 -05:00
Edward Minnix III
69fd5e93bc Merge pull request #28 from egregius313/egregisu313/webview-setAllowContentAccess-single-query
Merge `setAllowContentAccess` queries into singular query
2023-01-03 15:27:09 -05:00
Ed Minnix
81df89f93e Use proper @id in changenote 2023-01-03 15:19:26 -05:00
Ed Minnix
28ad9d00fb Merge both setAllowContentAccess queries into one query
Previously, the query to detect whether or not access to `content://`
links was done using two queries.

Now they can be merged into one query
2023-01-03 15:17:07 -05:00
Jami Cogswell
29221ae426 Java: add summary model for System.getProperty, adjust comments 2023-01-03 15:11:21 -05:00
Jami Cogswell
21a018e5c5 Java: add summary model and test for File.getName 2023-01-03 13:12:24 -05:00
Geoffrey White
fc646a6d48 Swift: Update .expected following a toString change in main. 2023-01-03 16:25:14 +00:00
Geoffrey White
e05bb7fcee Merge branch 'main' into format 2023-01-03 15:14:55 +00:00
Michael Nebel
17cd182d72 C#: Update stats based on projects. 2023-01-03 15:44:47 +01:00
Michael Nebel
9d608a78a3 C#: Add change note on renamed query ids. 2023-01-03 15:18:22 +01:00
Michael Nebel
bfe5a0c438 C#: Rename query id's to be prefixed with cs instead of csharp. 2023-01-03 15:13:54 +01:00
erik-krogh
3811eae679 simplify the qhelp for unsafe-code-construction
The `send()` example is not flagged by any current query, so it was weird talking about it as "vulnerable".
2023-01-02 13:33:56 +01:00
erik-krogh
3815a5a096 fix qhelp syntax 2023-01-02 10:19:05 +01:00
Ed Minnix
35de551f6b Formatting 2022-12-31 17:19:49 -05:00
Ed Minnix
515fa21aad Change notes 2022-12-31 17:18:37 -05:00
Ed Minnix
df1a4d2ed1 Documentation fix: Add state1 and state2 to documentation 2022-12-31 15:25:37 -05:00
Ed Minnix
68392aa8d8 Fix test expectations 2022-12-31 15:25:25 -05:00
Ed Minnix
02f70f3536 Add @security-severity tag 2022-12-31 15:00:28 -05:00
Edward Minnix III
1d345c6101 Refactoring and simplification
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2022-12-31 15:00:28 -05:00
Ed Minnix
9ef319f659 Java: setAllowContentAccess query tests 2022-12-31 15:00:28 -05:00
Ed Minnix
5265cb4b03 Merge two dataflow configurations into one taint tracking 2022-12-31 15:00:28 -05:00
Ed Minnix
973f649e76 Break dataflow into two steps in order to capture flow from WebView to settings call 2022-12-31 15:00:28 -05:00
Ed Minnix
0e15dd9fa9 Query metadata 2022-12-31 15:00:28 -05:00
Edward Minnix III
778749184b Change id to use android/ instead of prepending android-
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2022-12-31 15:00:28 -05:00
Ed Minnix
da25c586e6 Dataflow query for detecting paths that disable content access
Since the default value is `true`, we need to determine whether or not
the `setAllowContentAccess` method is ever called using dataflow.
2022-12-31 15:00:28 -05:00
Ed Minnix
8a763015e6 Reduce precision rating to medium
This query won't always be a security problem, so it should have a lower
precision rating than `high`.
2022-12-31 15:00:28 -05:00
Ed Minnix
7cc53126f3 Java: WebView setAllowContentAccess query test cases 2022-12-31 15:00:28 -05:00
Ed Minnix
a023726c03 Java: add Android stubs to options file for CWE-200 tests 2022-12-31 15:00:28 -05:00
Ed Minnix
e4e13d38b7 Java: query for Android WebView setAllowContentAccess 2022-12-31 15:00:28 -05:00
Ed Minnix
e259ef5d1d Java: Add class for android.webkit.WebSettings.setAllowContentAccess 2022-12-31 15:00:28 -05:00
Harry Maclean
a6571a05ab Ruby: Include send example in qhelp 2022-12-28 11:34:55 +13:00
Harry Maclean
d3812f5906 Ruby: Add another code injection example to qhelp 2022-12-28 11:20:56 +13:00
Tony Torralba
07d99bd643 Add path injection sinks 2022-12-23 17:16:06 +01:00
Tony Torralba
4215a89bc8 Add cleartext storage database sinks 2022-12-23 17:15:59 +01:00
Tony Torralba
ac39aeb6b6 Add SQLi sinks 2022-12-23 17:03:31 +01:00
Jami Cogswell
939279af38 Java: add comments 2022-12-22 16:25:12 -05:00
Jami Cogswell
673d37cc3d Java: update Math.min test case 2022-12-22 14:36:06 -05:00
Jami Cogswell
a81c54b58c Java: updates to order alphabetically 2022-12-22 13:22:12 -05:00
Jami Cogswell
e6331dc2e6 Java: update test case affected by Long.parseLong summary model 2022-12-22 12:57:37 -05:00
Jami Cogswell
997219a280 Java: update test case affected by Class.isAssignableFrom neutral model 2022-12-22 12:54:02 -05:00
Jami Cogswell
6007827dd3 Java: update test cases 2022-12-22 12:29:57 -05:00
Tony Torralba
36ca97e4f6 Add exclusions to reduce FP
Predicate parameters that have a database type are excluded.

Also, uses of the exists variable in an agreggation or another quantifier are excluded.
2022-12-22 11:15:07 +01:00
erik-krogh
b3dd50bc36 inline Location into the shared implementation of InlineExpectationsTest 2022-12-22 11:09:43 +01:00
Rasmus Lerchedahl Petersen
08e9d3391f swift: use shared inline tests
- add util shared pack to swift
 - remove from identical-files
2022-12-22 10:20:07 +01:00
Rasmus Lerchedahl Petersen
b0d7998342 go: use shared inline tests
- remove from identical-files
2022-12-22 10:20:07 +01:00
Rasmus Lerchedahl Petersen
f28eb6bf31 ql4ql: use shared inline tests
- add util shared pack to ql
 - remove from identical-files
2022-12-22 10:20:07 +01:00
Rasmus Lerchedahl Petersen
0d6c643d77 ruby: use shared inline tests
- remove from identical-files
2022-12-22 10:20:07 +01:00
Rasmus Lerchedahl Petersen
4667068017 java: use shared inline tests
- remove from identical-files
2022-12-22 10:20:06 +01:00
Rasmus Lerchedahl Petersen
a9b232bff4 csharp: use shared inline tests
- remove from identical-files
2022-12-22 10:20:06 +01:00
Rasmus Lerchedahl Petersen
d97e185994 cpp: use shared inline tests
- remove from identical-files
2022-12-22 10:20:06 +01:00
Rasmus Lerchedahl Petersen
e8d3802ee5 Python: use shared inline tests
- remove from identical-files
2022-12-22 10:20:05 +01:00
Rasmus Lerchedahl Petersen
b767dcfd18 shared: Add shared inline expectation test library 2022-12-22 10:20:05 +01:00
Jami Cogswell
de5965525f Java: add initial test cases for summary models 2022-12-21 16:19:37 -05:00
Jami Cogswell
c251da799f Java: update TopJdkApis test 2022-12-21 13:19:09 -05:00
Jami Cogswell
16de30e07e Java: add java.util.stream models 2022-12-21 13:05:23 -05:00
Jami Cogswell
1db829e55c Java: add java.util models 2022-12-21 13:03:57 -05:00
Jami Cogswell
573de92441 Java: add java.util.function models 2022-12-21 12:59:58 -05:00
Jami Cogswell
a8c55ee4b7 Java: add java.util.concurrent models 2022-12-21 12:59:00 -05:00
Jami Cogswell
db0d24fdd1 Java: add java.util.concurrent.atomic models 2022-12-21 12:57:22 -05:00
Jami Cogswell
cfe075ef54 Java: add java.time models 2022-12-21 12:54:35 -05:00
Jami Cogswell
8e20aeb314 Java: add java.text models 2022-12-21 12:51:44 -05:00
Jami Cogswell
b9ce588076 Java: add java.sql models 2022-12-21 12:49:29 -05:00
Jami Cogswell
1544f49f91 Java: add java.math models 2022-12-21 12:47:32 -05:00
Jami Cogswell
ed534b06d5 Java: add java.lang models 2022-12-21 12:45:12 -05:00
Jami Cogswell
99ddd484be Java: add java.io models 2022-12-21 12:34:26 -05:00
Tony Torralba
7d0018c897 Update ql/ql/src/queries/style/OmittableExists.ql 2022-12-21 17:16:34 +01:00
Tony Torralba
ac0c42c5c6 Apply suggestions from code review
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2022-12-21 16:16:58 +01:00
Tony Torralba
227e099854 Apply code review suggestions
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2022-12-21 12:40:29 +01:00
Tony Torralba
aa1d49cb95 Add OmittableExists QL-for-QL query 2022-12-21 12:26:58 +01:00
Paolo Tranquilli
454af0d721 Swift: fix locking of output swiftmodule trap 2022-12-20 15:34:18 +01:00
Paolo Tranquilli
a1161c6efe Swift: remove header patch which is not needed any more 2022-12-20 15:28:52 +01:00
Paolo Tranquilli
725861626c Merge branch 'main' into redsun82/swift-open-redirection 2022-12-20 15:28:30 +01:00
Tony Torralba
30aa9b230c Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2022-12-20 14:14:05 +01:00
turbo
d1d4163b79 Exclude cpp/wrong-use-of-the-umask 2022-12-18 15:55:04 +01:00
turbo
b7c33734b1 Merge remote-tracking branch 'origin/turbo/experimental/combined' into turbo/experimental/combined 2022-12-18 15:44:53 +01:00
turbo
1e5426fca2 Create security-experimental suite helper and all language suite implementations 2022-12-18 15:44:08 +01:00
Geoffrey White
640f894b00 Merge branch 'main' into format 2022-12-16 11:42:03 +00:00
Tony Torralba
46ea067449 Add bidirectional import in ExternalFlow.qll 2022-12-16 09:59:48 +01:00
Geoffrey White
1f7d96a74a Merge branch 'main' into format 2022-12-15 15:17:54 +00:00
Michael Nebel
2034b00772 C#: Remove deprecated ModelCsv classes. 2022-12-15 15:22:52 +01:00
Michael Nebel
0f038ee93a Java: Remove deprecated ModelCsv classes. 2022-12-15 15:22:44 +01:00
Paolo Tranquilli
7f505d8715 Swift: do not filter frontend actions 2022-12-15 14:39:43 +01:00
Paolo Tranquilli
208388e04d Swift: hard code libc.dylib path on macOS
Also, handle the corner case where loading libc fails.
2022-12-15 13:30:23 +01:00
Tony Torralba
6837af97bc Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2022-12-15 12:35:54 +01:00
Tony Torralba
11c03fb8c9 Add 'good' test cases 2022-12-15 12:35:47 +01:00
Paolo Tranquilli
3084eda28a Swift: add swiftmodule hash map testing to frontend_invocations 2022-12-15 10:33:47 +01:00
Paolo Tranquilli
e42ae09e1c Swift: fix interaction between bash wrapper and open redirection on macOS 2022-12-15 09:50:31 +01:00
turbo
5fd5ebc26e Create security-experimental suite helper and all language suite implementations 2022-12-14 23:35:32 +01:00
Paolo Tranquilli
793de3196b Revert "Swift: accept test changes"
This reverts commit 26ae8f177b.
2022-12-14 18:34:12 +01:00
Paolo Tranquilli
14fd89d482 Swift: generalize output redirection code 2022-12-14 18:26:48 +01:00
Paolo Tranquilli
45c0c7fe6c Merge branch 'main' into redsun82/swift-open-redirection 2022-12-14 18:26:16 +01:00
turbo
b35a1d4206 Adjust docs referring to experimental queries to include details on new tagging system 2022-12-14 17:16:38 +01:00
turbo
4ec401a3f6 Tag all security queries in supported languages' experimental directories with an experimental tag 2022-12-14 17:15:50 +01:00
Paolo Tranquilli
de2e92d5e1 Swift: remove / delimiters from regex extracted patterns 2022-12-14 09:18:36 +01:00
Paolo Tranquilli
fb5b6eab19 Swift: extract RegexLiteralExpr 2022-12-14 09:12:07 +01:00
erik-krogh
d95a4a7baf add a second example of how to use module_eval without constructing a code-string 2022-12-13 19:33:45 +01:00
erik-krogh
ccf520a5cd Merge branch 'main' into unsafeCodeConstruction 2022-12-13 18:31:49 +01:00
Tony Torralba
85b3092b16 Add security-severity and fix alert message 2022-12-13 12:01:01 +01:00
Tony Torralba
d72d096c86 Add predicate injection query 2022-12-13 10:27:29 +01:00
Paolo Tranquilli
250ac686a2 Merge branch 'main' into redsun82/swift-open-redirection 2022-12-12 08:46:23 +01:00
Paolo Tranquilli
a93e361aca Merge branch 'main' into redsun82/swift-open-redirection 2022-12-09 12:19:38 +01:00
Paolo Tranquilli
7162692656 Swift: exit directly on actions not requiring extraction 2022-12-09 10:00:01 +01:00
Paolo Tranquilli
4a41bb4061 Merge branch 'main' into redsun82/swift-open-redirection 2022-12-09 09:59:21 +01:00
Paolo Tranquilli
26ae8f177b Swift: accept test changes
Downgrading the emit object action to a type check one has some
unexpected side effects, that seem however acceptable:
* experimental false static assertions do not make compilation fail in
  type check mode
* the implicit module loading of `SwiftOnoneSupport` is not happening.
  That module contains some "pre-specializations", it does not seem
  really relevant for analysis
2022-12-08 17:13:00 +01:00
Paolo Tranquilli
d35c5e90ee Swift: remove fishhook 2022-12-08 16:10:44 +01:00
Paolo Tranquilli
bf1b32f210 Swift: rework file redirection
The hash map mechanism that was already in use for reading swiftmodule
files on macOS is now in use also on Linux. The output replacing
mechanism has been also reworked so that:
* frontend module emission modes have the remapping done directly in
  the internal frontend options instead of painstakingly modifying input
  flags (this requires a patch on the swift headers though)
* object emission mode is silenced to be just a type checking pass,
  thus producing no output files
* all other passes but some debugging and version related ones become
  noops

The open file read redirection uses a global weak pointer instance to
maximize robustness in the face of possibly multi-threaded calls to open
happening while `main` is exiting. Possibly overkill, but better safe
than sorry.
2022-12-08 16:10:44 +01:00
Paolo Tranquilli
944adfe727 Swift: allow modifying frontend outputs 2022-12-08 16:10:25 +01:00
Paolo Tranquilli
219ed64b74 Swift: reorganize bazel third party dependencies 2022-12-08 16:10:25 +01:00
Geoffrey White
24ce1c27bc Swift: Autoformat. 2022-12-08 13:09:37 +00:00
Geoffrey White
07ea006cee Swift: Add support for CSV modelled sinks as well. 2022-12-08 11:36:55 +00:00
Geoffrey White
dba344451f Swift: Add UncontrolledFormatStringExtensions.qll. 2022-12-08 11:32:50 +00:00
Geoffrey White
cf3345ee8f Swift: Revert security-severity on CWE-321, for now. 2022-12-02 12:01:43 +00:00
Geoffrey White
85a0a42da9 Swift: try again to satisfy ql-for-ql. 2022-12-02 10:15:11 +00:00
Geoffrey White
f7ebd1312e Swift: Corrections. 2022-12-01 20:13:56 +00:00
Geoffrey White
157a7829ca Swift: correct the example. 2022-12-01 18:35:10 +00:00
Geoffrey White
ad05cc3cb1 Swift: Separate out a FormatString library as well. 2022-12-01 18:09:46 +00:00
Geoffrey White
43596869e7 Swift: Move query logic to a .qll. 2022-12-01 18:09:45 +00:00
Geoffrey White
87fa159384 Swift: Add security-severity, and correct one for another query that apparently wasn't right. 2022-12-01 18:09:39 +00:00
Geoffrey White
58e9a0436e Swift: Add metadata. 2022-12-01 18:09:33 +00:00
Geoffrey White
2b61f26a64 Swift: Add doc. 2022-12-01 16:32:34 +00:00
Geoffrey White
32c4728f83 Swift: Add tests. 2022-12-01 16:32:33 +00:00
Geoffrey White
a2210959b5 Swift: Uncontrolled format string query (initial version). 2022-12-01 16:32:33 +00:00
erik-krogh
fd7442868f fix copy-pate error in UnsafeCodeConstructionQuery.qll 2022-11-28 13:45:24 +01:00
erik-krogh
f75b853ae4 add change-note 2022-11-25 11:08:14 +01:00
erik-krogh
53f24a5281 fix QL-for-QL warning 2022-11-25 10:32:06 +01:00
erik-krogh
0817238177 drive-by: same change in unsafe-shell-command-construction 2022-11-25 10:32:06 +01:00
erik-krogh
378cc1aed2 add support for string-like-literals 2022-11-25 10:32:06 +01:00
erik-krogh
80c92dc3e6 add support for array pushes 2022-11-25 10:32:05 +01:00
erik-krogh
3461404bbb add basic support for arrays 2022-11-25 10:31:35 +01:00
erik-krogh
0f2a48f461 fix QL-for-QL warnings 2022-11-25 10:26:24 +01:00
erik-krogh
2033dd2dcc remove parameters named "code" as source 2022-11-25 10:25:31 +01:00
erik-krogh
e7c6571f52 remove the "send(..)" and similar from unsafe-code-construction 2022-11-25 10:25:31 +01:00
erik-krogh
f1668801d3 add a rb/unsafe-code-construction query
rebase
2022-11-25 10:25:30 +01:00
erik-krogh
5f6cb1684b move the code-injection tests into a subfolder 2022-11-24 17:23:25 +01:00
erik-krogh
2ad28ab4db add library inputs as a source to poly-redos 2022-11-22 13:05:34 +01:00
Rasmus Lerchedahl Petersen
0a7cfad048 python: inline query tests for command injection
note how the test file is partially annotated
and those annotations can now be expressed

In this particular test file, absolute line numbers
might have been better than relative ones.
We might remove line numbers altogether,
but should check more querries to see how it looks.
2022-11-02 16:21:59 +01:00
Rasmus Lerchedahl Petersen
f486c44b00 python: library for inline query tests
similar to the consistency queires used in js
but based on the inline expectations framework
2022-11-02 16:18:36 +01:00
ihsinme
65c9a7b278 Update BufferAccessWithIncorrectLengthValue.ql 2022-06-26 13:49:44 +03:00
ihsinme
c1f0940b6a Update cpp/ql/src/experimental/Security/CWE/CWE-805/BufferAccessWithIncorrectLengthValue.ql
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2022-06-23 12:50:59 +03:00
ihsinme
5609d5200b Update cpp/ql/src/experimental/Security/CWE/CWE-805/BufferAccessWithIncorrectLengthValue.ql
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2022-05-30 20:41:39 +03:00
ihsinme
9499961a9c Update BufferAccessWithIncorrectLengthValue.ql 2022-05-30 12:43:28 +03:00
ihsinme
d489c12014 Update BufferAccessWithIncorrectLengthValue.ql 2022-05-30 12:26:26 +03:00
ihsinme
475e36e6fc Update BufferAccessWithIncorrectLengthValue.ql 2022-05-29 09:58:16 +03:00
ihsinme
df1ea5b679 Update BufferAccessWithIncorrectLengthValue.qhelp 2022-05-29 09:56:29 +03:00
ihsinme
5a9061e45b create new branchihsinme-patch-102 in fork 2022-05-21 14:19:34 +00:00
2548 changed files with 442196 additions and 45340 deletions

View File

@@ -19,4 +19,6 @@ runs:
gh extension install github/gh-codeql
gh codeql set-channel "$CHANNEL"
gh codeql version
printf "CODEQL_FETCHED_CODEQL_PATH=" >> "${GITHUB_ENV}"
gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_ENV}"
gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_PATH}"

View File

@@ -1,26 +0,0 @@
name: Find Latest CodeQL Bundle
description: Finds the URL of the latest released version of the CodeQL bundle.
outputs:
url:
description: The download URL of the latest CodeQL bundle release
value: ${{ steps.find-latest.outputs.url }}
runs:
using: composite
steps:
- name: Find Latest Release
id: find-latest
shell: pwsh
run: |
$Latest = gh release list --repo github/codeql-action --exclude-drafts --limit 1000 |
ForEach-Object { $C = $_ -split "`t"; return @{ type = $C[1]; tag = $C[2]; } } |
Where-Object { $_.type -eq 'Latest' }
$Tag = $Latest.tag
if ($Tag -eq '') {
throw 'Failed to find latest bundle release.'
}
Write-Output "Latest bundle tag is '${Tag}'."
"url=https://github.com/github/codeql-action/releases/download/${Tag}/codeql-bundle-linux64.tar.gz" >> $env:GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ github.token }}

32
.github/actions/os-version/action.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: OS Version
description: Get OS version.
outputs:
version:
description: "OS version"
value: ${{ steps.version.outputs.version }}
runs:
using: composite
steps:
- if: runner.os == 'Linux'
shell: bash
run: |
. /etc/os-release
echo "VERSION=${NAME} ${VERSION}" >> $GITHUB_ENV
- if: runner.os == 'Windows'
shell: powershell
run: |
$objects = systeminfo.exe /FO CSV | ConvertFrom-Csv
"VERSION=$($objects.'OS Name') $($objects.'OS Version')" >> $env:GITHUB_ENV
- if: runner.os == 'macOS'
shell: bash
run: |
echo "VERSION=$(sw_vers -productName) $(sw_vers -productVersion)" >> $GITHUB_ENV
- name: Emit OS version
id: version
shell: bash
run: |
echo "$VERSION"
echo "version=${VERSION}" >> $GITHUB_OUTPUT

View File

@@ -1,19 +1,12 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "ruby/node-types"
directory: "ruby"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "ruby/generator"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "ruby/extractor"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "ruby/autobuilder"
directory: "ql"
schedule:
interval: "daily"

View File

@@ -26,3 +26,9 @@ jobs:
run: |
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' |
grep true -c
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md' or 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text.
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$"))' |
grep true -c

View File

@@ -28,9 +28,9 @@ jobs:
steps:
- name: Setup dotnet
uses: actions/setup-dotnet@v2
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.202
dotnet-version: 7.0.102
- name: Checkout repository
uses: actions/checkout@v3

View File

@@ -77,10 +77,10 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.202
dotnet-version: 7.0.102
- name: Extractor unit tests
run: |
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/extractor/Semmle.Util.Tests"
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/extractor/Semmle.Extraction.Tests"
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests"
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/csharp/extractor/Semmle.Util.Tests"
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/csharp/extractor/Semmle.Extraction.Tests"
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests"
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"

View File

@@ -12,10 +12,10 @@ jobs:
name: Test MacOS
runs-on: macos-latest
steps:
- name: Set up Go 1.19
- name: Set up Go 1.20
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.20.0
id: go
- name: Check out code
@@ -47,10 +47,10 @@ jobs:
name: Test Windows
runs-on: windows-latest-xl
steps:
- name: Set up Go 1.19
- name: Set up Go 1.20
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.20.0
id: go
- name: Check out code

View File

@@ -20,10 +20,10 @@ jobs:
name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl
steps:
- name: Set up Go 1.19
- name: Set up Go 1.20
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.20.0
id: go
- name: Check out code

View File

@@ -11,7 +11,7 @@ on:
branches:
- main
paths:
- "java/ql/src/utils/model-generator/**/*.*"
- "java/ql/src/utils/modelgenerator/**/*.*"
- ".github/workflows/mad_modelDiff.yml"
permissions:
@@ -40,12 +40,12 @@ jobs:
- name: Download database
env:
SLUG: ${{ matrix.slug }}
GH_TOKEN: ${{ github.token }}
run: |
set -x
mkdir lib-dbs
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
projectId=`curl -s https://lgtm.com/api/v1.0/projects/g/${SLUG} | jq .id`
curl -L "https://lgtm.com/api/v1.0/snapshots/$projectId/java" -o "$SHORTNAME.zip"
gh api -H "Accept: application/zip" "/repos/${SLUG}/code-scanning/codeql/databases/java" > "$SHORTNAME.zip"
unzip -q -d "${SHORTNAME}-db" "${SHORTNAME}.zip"
mkdir "lib-dbs/$SHORTNAME/"
mv "${SHORTNAME}-db/"$(ls -1 "${SHORTNAME}"-db)/* "lib-dbs/${SHORTNAME}/"
@@ -61,7 +61,7 @@ jobs:
DATABASE=$2
cd codeql-$QL_VARIANT
SHORTNAME=`basename $DATABASE`
python java/ql/src/utils/model-generator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE ${SHORTNAME}.temp.model.yml
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE ${SHORTNAME}.temp.model.yml
mv java/ql/lib/ext/generated/${SHORTNAME}.temp.model.yml $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.model.yml
cd ..
}
@@ -100,4 +100,6 @@ jobs:
with:
name: diffs
path: tmp-models/*.html
# An html file is only produced if the generated models differ.
if-no-files-found: ignore
retention-days: 20

View File

@@ -50,7 +50,7 @@ jobs:
SLUG: ${{ matrix.slug }}
run: |
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
java/ql/src/utils/model-generator/RegenerateModels.py "${SLUG}" dbs/${SHORTNAME}
java/ql/src/utils/modelgenerator/RegenerateModels.py "${SLUG}" dbs/${SHORTNAME}
- name: Stage changes
run: |
find java -name "*.model.yml" -print0 | xargs -0 git add

View File

@@ -22,142 +22,54 @@ jobs:
steps:
### Build the queries ###
- uses: actions/checkout@v3
- name: Find latest bundle
id: find-latest-bundle
uses: ./.github/actions/find-latest-bundle
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@77a8d2d10c0b403a8b4aadbd223dc489ecd22683
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
tools: ${{ steps.find-latest-bundle.outputs.url }}
- name: Get CodeQL version
id: get-codeql-version
run: |
echo "version=$("${CODEQL}" --version | head -n 1 | rev | cut -d " " -f 1 | rev)" >> $GITHUB_OUTPUT
shell: bash
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Cache entire pack
id: cache-pack
uses: actions/cache@v3
with:
path: ${{ runner.temp }}/pack
key: ${{ runner.os }}-pack-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}--${{ hashFiles('.github/workflows/ql-for-ql-build.yml') }}
- name: Cache queries
if: steps.cache-pack.outputs.cache-hit != 'true'
id: cache-queries
uses: actions/cache@v3
with:
path: ${{ runner.temp }}/queries
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}--${{ hashFiles('.github/workflows/ql-for-ql-build.yml') }}
- name: Build query pack
if: steps.cache-queries.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
run: |
cd ql/ql/src
"${CODEQL}" pack create -j 16
mv .codeql/pack/codeql/ql/0.0.0 ${{ runner.temp }}/queries
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Move cache queries to pack
if: steps.cache-pack.outputs.cache-hit != 'true'
run: |
cp -r ${{ runner.temp }}/queries ${{ runner.temp }}/pack
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- uses: ./.github/actions/os-version
id: os_version
### Build the extractor ###
- name: Cache entire extractor
if: steps.cache-pack.outputs.cache-hit != 'true'
id: cache-extractor
uses: actions/cache@v3
with:
path: |
ql/target/release/ql-autobuilder
ql/target/release/ql-autobuilder.exe
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
path: ql/extractor-pack/
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
- name: Cache cargo
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
run: cd ql; cargo fmt --all -- --check
- name: Build
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
run: cd ql; cargo build --verbose
- name: Run tests
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
run: cd ql; cargo test --verbose
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Release build
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
run: cd ql; cargo build --release
- name: Generate dbscheme
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
### Package the queries and extractor ###
- name: Package pack
if: steps.cache-pack.outputs.cache-hit != 'true'
run: |
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats ${PACK}/
mkdir -p ${PACK}/tools/linux64
cp ql/target/release/ql-autobuilder ${PACK}/tools/linux64/autobuilder
cp ql/target/release/ql-extractor ${PACK}/tools/linux64/extractor
chmod +x ${PACK}/tools/linux64/autobuilder
chmod +x ${PACK}/tools/linux64/extractor
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; ./scripts/create-extractor-pack.sh
env:
PACK: ${{ runner.temp }}/pack
### Run the analysis ###
- name: Hack codeql-action options
GH_TOKEN: ${{ github.token }}
- name: Cache compilation cache
id: query-cache
uses: ./.github/actions/cache-query-compilation
with:
key: run-ql-for-ql
- name: Make database and analyze
run: |
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .resolve.languages=["--search-path", $pack] | .database.init=["--search-path", $pack]')
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
env:
PACK: ${{ runner.temp }}/pack
- name: Create CodeQL config file
run: |
echo "paths-ignore:" >> ${CONF}
echo " - ql/ql/test" >> ${CONF}
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
echo "disable-default-queries: true" >> ${CONF}
echo "queries:" >> ${CONF}
echo " - uses: ./ql/ql/src/codeql-suites/ql-code-scanning.qls" >> ${CONF}
echo "Config file: "
cat ${CONF}
env:
CONF: ./ql-for-ql-config.yml
- name: Initialize CodeQL
uses: github/codeql-action/init@77a8d2d10c0b403a8b4aadbd223dc489ecd22683
${CODEQL} database create -l=ql --search-path ql/extractor-pack ${DB}
${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
DB: ${{ runner.temp }}/DB
LGTM_INDEX_FILTERS: |
exclude:ql/ql/test
exclude:*/ql/lib/upgrades/
- name: Upload sarif to code-scanning
uses: github/codeql-action/upload-sarif@v2
with:
languages: ql
db-location: ${{ runner.temp }}/db
config-file: ./ql-for-ql-config.yml
tools: ${{ steps.find-latest-bundle.outputs.url }}
- name: Move pack cache
run: |
cp -r ${PACK}/.cache ql/ql/src/.cache
env:
PACK: ${{ runner.temp }}/pack
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@77a8d2d10c0b403a8b4aadbd223dc489ecd22683
with:
category: "ql-for-ql"
- name: Copy sarif file to CWD
run: cp ../results/ql.sarif ./ql-for-ql.sarif
- name: Fixup the $scema in sarif # Until https://github.com/microsoft/sarif-vscode-extension/pull/436/ is part in a stable release
run: |
sed -i 's/\$schema.*/\$schema": "https:\/\/raw.githubusercontent.com\/oasis-tcs\/sarif-spec\/master\/Schemata\/sarif-schema-2.1.0",/' ql-for-ql.sarif
sarif_file: ql-for-ql.sarif
category: ql-for-ql
- name: Sarif as artifact
uses: actions/upload-artifact@v3
with:
@@ -172,4 +84,4 @@ jobs:
with:
name: ql-for-ql-langs
path: split-sarif
retention-days: 1
retention-days: 1

View File

@@ -25,16 +25,18 @@ jobs:
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@77a8d2d10c0b403a8b4aadbd223dc489ecd22683
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version
id: os_version
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Build Extractor
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./scripts/create-extractor-pack.sh
env:

View File

@@ -6,11 +6,13 @@ on:
paths:
- "ql/**"
- codeql-workspace.yml
- .github/workflows/ql-for-ql-tests.yml
pull_request:
branches: [main]
paths:
- "ql/**"
- codeql-workspace.yml
- .github/workflows/ql-for-ql-tests.yml
env:
CARGO_TERM_COLOR: always
@@ -22,28 +24,86 @@ jobs:
- uses: actions/checkout@v3
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@77a8d2d10c0b403a8b4aadbd223dc489ecd22683
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version
id: os_version
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-qltest-cargo-${{ hashFiles('ql/rust-toolchain.toml', 'ql/**/Cargo.lock') }}
- name: Check formatting
run: cd ql; cargo fmt --all -- --check
- name: Build extractor
run: |
cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./scripts/create-extractor-pack.sh
- name: Cache compilation cache
id: query-cache
uses: ./.github/actions/cache-query-compilation
with:
key: ql-for-ql-tests
- name: Run QL tests
run: |
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" ql/ql/test
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL formatting
other-os:
strategy:
matrix:
os: [macos-latest, windows-latest]
needs: [qltest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install GNU tar
if: runner.os == 'macOS'
run: |
find ql/ql/src "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
brew install gnu-tar
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version
id: os_version
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-qltest-cargo-${{ hashFiles('ql/rust-toolchain.toml', 'ql/**/Cargo.lock') }}
- name: Build extractor
if: runner.os != 'Windows'
run: |
cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./scripts/create-extractor-pack.sh
- name: Build extractor (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
cd ql;
$Env:PATH += ";$(dirname ${{ steps.find-codeql.outputs.codeql-path }})"
pwsh ./scripts/create-extractor-pack.ps1
- name: Run a single QL tests - Unix
if: runner.os != 'Windows'
run: |
"${CODEQL}" test run --check-databases --search-path "${{ github.workspace }}/ql/extractor-pack" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Run a single QL tests - Windows
if: runner.os == 'Windows'
shell: pwsh
run: |
$Env:PATH += ";$(dirname ${{ steps.find-codeql.outputs.codeql-path }})"
codeql test run --check-databases --search-path "${{ github.workspace }}/ql/extractor-pack" ql/ql/test/queries/style/DeadCode/DeadCode.qlref

View File

@@ -48,6 +48,8 @@ jobs:
run: |
brew install gnu-tar
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
- uses: ./.github/actions/os-version
id: os_version
- name: Cache entire extractor
uses: actions/cache@v3
id: cache-extractor
@@ -58,7 +60,7 @@ jobs:
ruby/target/release/ruby-extractor
ruby/target/release/ruby-extractor.exe
ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
key: ${{ runner.os }}-ruby-extractor-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}--${{ hashFiles('ruby/**/*.rs') }}
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}--${{ hashFiles('ruby/**/*.rs') }}
- uses: actions/cache@v3
if: steps.cache-extractor.outputs.cache-hit != 'true'
with:
@@ -66,7 +68,7 @@ jobs:
~/.cargo/registry
~/.cargo/git
ruby/target
key: ${{ runner.os }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
- name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cargo fmt --all -- --check
@@ -203,11 +205,6 @@ jobs:
- name: Fetch CodeQL
uses: ./.github/actions/fetch-codeql
- uses: actions/checkout@v3
with:
repository: Shopify/example-ruby-app
ref: 67a0decc5eb550f3a9228eda53925c3afd40dfe9
- name: Download Ruby bundle
uses: actions/download-artifact@v3
with:
@@ -216,26 +213,15 @@ jobs:
- name: Unzip Ruby bundle
shell: bash
run: unzip -q -d "${{ runner.temp }}/ruby-bundle" "${{ runner.temp }}/codeql-ruby-bundle.zip"
- name: Prepare test files
shell: bash
run: |
echo "import codeql.ruby.AST select count(File f)" > "test.ql"
echo "| 4 |" > "test.expected"
echo 'name: sample-tests
version: 0.0.0
dependencies:
codeql/ruby-all: "*"
extractor: ruby
tests: .
' > qlpack.yml
- name: Run QL test
shell: bash
run: |
codeql test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" .
codeql test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" ruby/ql/test/library-tests/ast/constants/
- name: Create database
shell: bash
run: |
codeql database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root . ../database
codeql database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root ruby/ql/test/library-tests/ast/constants/ ../database
- name: Analyze database
shell: bash
run: |

View File

@@ -25,6 +25,7 @@ If you have an idea for a query that you would like to share with other CodeQL u
Each language-specific directory contains further subdirectories that group queries based on their `@tags` or purpose.
- Experimental queries and libraries are stored in the `experimental` subdirectory within each language-specific directory in the [CodeQL repository](https://github.com/github/codeql). For example, experimental Java queries and libraries are stored in `java/ql/src/experimental` and any corresponding tests in `java/ql/test/experimental`.
- Experimental queries need to include `experimental` in their `@tags`
- The structure of an `experimental` subdirectory mirrors the structure of its parent directory.
- Select or create an appropriate directory in `experimental` based on the existing directory structure of `experimental` or its parent directory.

View File

@@ -10,6 +10,8 @@ There is [extensive documentation](https://codeql.github.com/docs/) on getting s
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/main/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
For information on contributing to CodeQL documentation, see the "[contributing guide](docs/codeql/CONTRIBUTING.md)" for docs.
## License
The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com).

View File

@@ -29,13 +29,14 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll",
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll",
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll",
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
@@ -402,16 +403,6 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll"
],
"Inline Test Expectations": [
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"csharp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll",
"go/ql/test/TestUtilities/InlineExpectationsTest.qll",
"swift/ql/test/TestUtilities/InlineExpectationsTest.qll"
],
"C++ ExternalAPIs": [
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
"cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll"

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
<ApplicationIcon />

View File

@@ -13,5 +13,5 @@ predicate isExprWithNewBuiltin(Expr expr) {
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 0 else kind_new = kind
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

View File

@@ -9,5 +9,5 @@ class Location extends @location_expr {
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if expr instanceof @blockassignexpr then kind_new = 0 else kind_new = kind
if expr instanceof @blockassignexpr then kind_new = 1 else kind_new = kind
select expr, kind_new, location

View File

@@ -0,0 +1,11 @@
class BuiltinType extends @builtintype {
string toString() { none() }
}
from BuiltinType type, string name, int kind, int kind_new, int size, int sign, int alignment
where
builtintypes(type, name, kind, size, sign, alignment) and
if type instanceof @float16 or type instanceof @complex_float16
then kind_new = 2
else kind_new = kind
select type, name, kind_new, size, sign, alignment

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Introduce (_Complex) _Float16 type
compatibility: backwards
builtintypes.rel: run builtintypes.qlo

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Uncomment case splits in dbscheme
compatibility: full

View File

@@ -1,3 +1,15 @@
## 0.5.3
No user-facing changes.
## 0.5.2
No user-facing changes.
## 0.5.1
No user-facing changes.
## 0.5.0
### Breaking Changes

View File

@@ -0,0 +1,3 @@
## 0.5.1
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 0.5.2
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 0.5.3
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.5.0
lastReleaseVersion: 0.5.3

View File

@@ -123,6 +123,13 @@ private predicate constructorCallTypeMention(ConstructorCall cc, TypeMention tm)
)
}
/** Holds if `loc` has the container `container` and is on the line starting at `startLine`. */
pragma[nomagic]
private predicate hasContainerAndStartLine(Location loc, Container container, int startLine) {
loc.getStartLine() = startLine and
loc.getContainer() = container
}
/**
* Gets an element, of kind `kind`, that element `e` uses, if any.
* Attention: This predicate yields multiple definitions for a single location.
@@ -159,9 +166,9 @@ Top definitionOf(Top e, string kind) {
// Multiple type mentions can be generated when a typedef is used, and
// in such cases we want to exclude all but the originating typedef.
not exists(Type secondary |
exists(TypeMention tm, File f, int startline, int startcol |
exists(File f, int startline, int startcol |
typeMentionStartLoc(e, result, f, startline, startcol) and
typeMentionStartLoc(tm, secondary, f, startline, startcol) and
typeMentionStartLoc(_, secondary, f, startline, startcol) and
(
result = secondary.(TypedefType).getBaseType() or
result = secondary.(TypedefType).getBaseType().(SpecifiedType).getBaseType()
@@ -184,11 +191,9 @@ Top definitionOf(Top e, string kind) {
kind = "I" and
result = e.(Include).getIncludedFile() and
// exclude `#include` directives containing macros
not exists(MacroInvocation mi, Location l1, Location l2 |
l1 = e.(Include).getLocation() and
l2 = mi.getLocation() and
l1.getContainer() = l2.getContainer() and
l1.getStartLine() = l2.getStartLine()
not exists(MacroInvocation mi, Container container, int startLine |
hasContainerAndStartLine(e.(Include).getLocation(), container, startLine) and
hasContainerAndStartLine(mi.getLocation(), container, startLine)
// (an #include directive must be always on it's own line)
)
) and

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or
@@ -1391,6 +1391,9 @@ class TypedContentApprox extends MkTypedContentApprox {
/** Gets a typed content approximated by this value. */
TypedContent getATypedContent() { result = getATypedContent(this) }
/** Gets the content. */
ContentApprox getContent() { result = c }
/** Gets the container type. */
DataFlowType getContainerType() { result = t }
@@ -1408,6 +1411,8 @@ abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
abstract boolean toBoolNonEmpty();
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
pragma[nomagic]
TypedContent getAHead() {
exists(TypedContentApprox cont |

View File

@@ -45,6 +45,16 @@ module Consistency {
) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodeAtPosition`. */
predicate uniqueParameterNodeAtPositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodePosition`. */
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
}
private class RelevantNode extends Node {
@@ -101,9 +111,7 @@ module Consistency {
exists(int c |
c =
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not n.hasLocationInfo(_, _, _, _, _) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
) and
msg = "Nodes without location: " + c
@@ -248,6 +256,7 @@ module Consistency {
query predicate uniqueParameterNodeAtPosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodeAtPositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(Node p0 | isParameterNode(p0, c, pos))) and
msg = "Parameters with overlapping positions."
@@ -256,6 +265,7 @@ module Consistency {
query predicate uniqueParameterNodePosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodePositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and
msg = "Parameter node with multiple positions."

View File

@@ -218,7 +218,7 @@ private predicate allocation(Instruction array, Length length, int delta) {
length.(VNLength).getInstruction().getConvertedResultExpression() = lengthExpr
)
or
not exists(int d | deconstructMallocSizeExpr(alloc.getSizeExpr(), _, d)) and
not deconstructMallocSizeExpr(alloc.getSizeExpr(), _, _) and
length.(VNLength).getInstruction().getConvertedResultExpression() = alloc.getSizeExpr() and
delta = 0
)

View File

@@ -543,9 +543,7 @@ private predicate boundedPhiCand(
PhiInstruction phi, boolean upper, Bound b, int delta, boolean fromBackEdge, int origdelta,
Reason reason
) {
exists(PhiInputOperand op |
boundedPhiInp(phi, op, b, delta, upper, fromBackEdge, origdelta, reason)
)
boundedPhiInp(phi, _, b, delta, upper, fromBackEdge, origdelta, reason)
}
/**

View File

@@ -0,0 +1,263 @@
private import cpp
private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
float evaluateConstantExpr(Expr e) {
result = e.getValue().toFloat()
or
// This handles when a constant value is put into a variable
// and the variable is used later
exists(SsaDefinition defn, StackVariable sv |
defn.getAUse(sv) = e and
result = defn.getDefiningValue(sv).getValue().toFloat()
)
}
// If the constant right operand is negative or is greater than or equal to the number of
// bits in the left operands type, then the result is undefined (except on the IA-32
// architecture where the shift value is masked with 0b00011111, but we can't
// assume the architecture).
bindingset[val]
private predicate isValidShiftExprShift(float val, Expr l) {
val >= 0 and
// We use getFullyConverted because the spec says to use the *promoted* left operand
val < (l.getFullyConverted().getUnderlyingType().getSize() * 8)
}
bindingset[val, shift, max_val]
private predicate canLShiftOverflow(int val, int shift, int max_val) {
// val << shift = val * 2^shift > max_val => val > max_val/2^shift = max_val >> b
val > max_val.bitShiftRight(shift)
}
/**
* A range analysis expression consisting of the `>>` or `>>=` operator when at least
* one operand is a constant (and if the right operand is a constant, it must be "valid"
* (see `isValidShiftExprShift`)). When handling any undefined behavior, it leaves the
* values unconstrained. From the C++ standard: "The behavior is undefined if the right
* operand is negative, or greater than or equal to the length in bits of the promoted
* left operand. The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an
* unsigned type or if E1 has a signed type and a non-negative value, the value of the
* result is the integral part of the quotient of E1/2^E2. If E1 has a signed type and a
* negative value, the resulting value is implementation-defined."
*/
class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
/**
* Holds for `a >> b` or `a >>= b` in one of the following two cases:
* 1. `a` is a constant and `b` is not
* 2. `b` is constant
*
* We don't handle the case where `a` and `b` are both non-constant values.
*/
ConstantRShiftExprRange() {
getUnspecifiedType() instanceof IntegralType and
exists(Expr l, Expr r |
l = this.(RShiftExpr).getLeftOperand() and
r = this.(RShiftExpr).getRightOperand()
or
l = this.(AssignRShiftExpr).getLValue() and
r = this.(AssignRShiftExpr).getRValue()
|
l.getUnspecifiedType() instanceof IntegralType and
r.getUnspecifiedType() instanceof IntegralType and
(
// If the left operand is a constant, verify that the right operand is not a constant
exists(evaluateConstantExpr(l)) and not exists(evaluateConstantExpr(r))
or
// If the right operand is a constant, check if it is a valid shift expression
exists(float constROp |
constROp = evaluateConstantExpr(r) and isValidShiftExprShift(constROp, l)
)
)
)
}
Expr getLeftOperand() {
result = this.(RShiftExpr).getLeftOperand() or
result = this.(AssignRShiftExpr).getLValue()
}
Expr getRightOperand() {
result = this.(RShiftExpr).getRightOperand() or
result = this.(AssignRShiftExpr).getRValue()
}
override float getLowerBounds() {
exists(int lLower, int lUpper, int rLower, int rUpper |
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
lLower <= lUpper and
rLower <= rUpper
|
if
lLower < 0
or
not (
isValidShiftExprShift(rLower, getLeftOperand()) and
isValidShiftExprShift(rUpper, getLeftOperand())
)
then
// We don't want to deal with shifting negative numbers at the moment,
// and a negative shift is implementation defined, so we set the result
// to the minimum value
result = exprMinVal(this)
else
// We can get the smallest value by shifting the smallest bound by the largest bound
result = lLower.bitShiftRight(rUpper)
)
}
override float getUpperBounds() {
exists(int lLower, int lUpper, int rLower, int rUpper |
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
lLower <= lUpper and
rLower <= rUpper
|
if
lLower < 0
or
not (
isValidShiftExprShift(rLower, getLeftOperand()) and
isValidShiftExprShift(rUpper, getLeftOperand())
)
then
// We don't want to deal with shifting negative numbers at the moment,
// and a negative shift is implementation defined, so we set the result
// to the maximum value
result = exprMaxVal(this)
else
// We can get the largest value by shifting the largest bound by the smallest bound
result = lUpper.bitShiftRight(rLower)
)
}
override predicate dependsOnChild(Expr child) {
child = getLeftOperand() or child = getRightOperand()
}
}
/**
* A range analysis expression consisting of the `<<` or `<<=` operator when at least
* one operand is a constant (and if the right operand is a constant, it must be "valid"
* (see `isValidShiftExprShift`)). When handling any undefined behavior, it leaves the
* values unconstrained. From the C++ standard: "The behavior is undefined if the right
* operand is negative, or greater than or equal to the length in bits of the promoted left operand.
* The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1
* has an unsigned type, the value of the result is E1 x 2 E2, reduced modulo one more than the
* maximum value representable in the result type. Otherwise, if E1 has a signed type and
* non-negative value, and E1 x 2 E2 is representable in the corresponding unsigned type of the
* result type, then that value, converted to the result type, is the resulting value; otherwise,
* the behavior is undefined."
*/
class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
/**
* Holds for `a << b` or `a <<= b` in one of the following two cases:
* 1. `a` is a constant and `b` is not
* 2. `b` is constant
*
* We don't handle the case where `a` and `b` are both non-constant values.
*/
ConstantLShiftExprRange() {
getUnspecifiedType() instanceof IntegralType and
exists(Expr l, Expr r |
l = this.(LShiftExpr).getLeftOperand() and
r = this.(LShiftExpr).getRightOperand()
or
l = this.(AssignLShiftExpr).getLValue() and
r = this.(AssignLShiftExpr).getRValue()
|
l.getUnspecifiedType() instanceof IntegralType and
r.getUnspecifiedType() instanceof IntegralType and
(
// If the left operand is a constant, verify that the right operand is not a constant
exists(evaluateConstantExpr(l)) and not exists(evaluateConstantExpr(r))
or
// If the right operand is a constant, check if it is a valid shift expression
exists(float constROp |
constROp = evaluateConstantExpr(r) and isValidShiftExprShift(constROp, l)
)
)
)
}
Expr getLeftOperand() {
result = this.(LShiftExpr).getLeftOperand() or
result = this.(AssignLShiftExpr).getLValue()
}
Expr getRightOperand() {
result = this.(LShiftExpr).getRightOperand() or
result = this.(AssignLShiftExpr).getRValue()
}
override float getLowerBounds() {
exists(int lLower, int lUpper, int rLower, int rUpper |
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
lLower <= lUpper and
rLower <= rUpper
|
if
lLower < 0
or
not (
isValidShiftExprShift(rLower, getLeftOperand()) and
isValidShiftExprShift(rUpper, getLeftOperand())
)
then
// We don't want to deal with shifting negative numbers at the moment,
// and a negative shift is undefined, so we set to the minimum value
result = exprMinVal(this)
else
// If we have `0b01010000 << [0, 2]`, the max value for 8 bits is 0b10100000
// (a shift of 1) but doing a shift by the upper bound would give 0b01000000.
// So if the left shift operation causes an overflow, we just assume the max value
// If necessary, we may be able to improve this bound in the future
if canLShiftOverflow(lUpper, rUpper, exprMaxVal(this))
then result = exprMinVal(this)
else result = lLower.bitShiftLeft(rLower)
)
}
override float getUpperBounds() {
exists(int lLower, int lUpper, int rLower, int rUpper |
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
lLower <= lUpper and
rLower <= rUpper
|
if
lLower < 0
or
not (
isValidShiftExprShift(rLower, getLeftOperand()) and
isValidShiftExprShift(rUpper, getLeftOperand())
)
then
// We don't want to deal with shifting negative numbers at the moment,
// and a negative shift is undefined, so we set it to the maximum value
result = exprMaxVal(this)
else
// If we have `0b01010000 << [0, 2]`, the max value for 8 bits is 0b10100000
// (a shift of 1) but doing a shift by the upper bound would give 0b01000000.
// So if the left shift operation causes an overflow, we just assume the max value
// If necessary, we may be able to improve this bound in the future
if canLShiftOverflow(lUpper, rUpper, exprMaxVal(this))
then result = exprMaxVal(this)
else result = lUpper.bitShiftLeft(rUpper)
)
}
override predicate dependsOnChild(Expr child) {
child = getLeftOperand() or child = getRightOperand()
}
}

View File

@@ -0,0 +1,29 @@
private import RangeAnalysisStage
module FloatDelta implements DeltaSig {
class Delta = float;
bindingset[d]
bindingset[result]
float toFloat(Delta d) { result = d }
bindingset[d]
bindingset[result]
int toInt(Delta d) { result = d }
bindingset[n]
bindingset[result]
Delta fromInt(int n) { result = n }
bindingset[f]
Delta fromFloat(float f) {
result =
min(float diff, float res |
diff = (res - f) and res = f.ceil()
or
diff = (f - res) and res = f.floor()
|
res order by diff
)
}
}

View File

@@ -14,321 +14,328 @@ private import ModulusAnalysisSpecific::Private
private import experimental.semmle.code.cpp.semantic.Semantic
private import ConstantAnalysis
private import RangeUtils
private import RangeAnalysisStage
/**
* Holds if `e + delta` equals `v` at `pos`.
*/
private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) {
semSsaUpdateStep(v, e, delta) and pos.hasReadOfVar(v)
or
exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = semEqFlowCond(v, e, delta, true, testIsTrue) and
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue)
)
}
/**
* Holds if `add` is the addition of `larg` and `rarg`, neither of which are
* `ConstantIntegerExpr`s.
*/
private predicate nonConstAddition(SemExpr add, SemExpr larg, SemExpr rarg) {
exists(SemAddExpr a | a = add |
larg = a.getLeftOperand() and
rarg = a.getRightOperand()
) and
not larg instanceof SemConstantIntegerExpr and
not rarg instanceof SemConstantIntegerExpr
}
/**
* Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not
* a `ConstantIntegerExpr`.
*/
private predicate nonConstSubtraction(SemExpr sub, SemExpr larg, SemExpr rarg) {
exists(SemSubExpr s | s = sub |
larg = s.getLeftOperand() and
rarg = s.getRightOperand()
) and
not rarg instanceof SemConstantIntegerExpr
}
/** Gets an expression that is the remainder modulo `mod` of `arg`. */
private SemExpr modExpr(SemExpr arg, int mod) {
exists(SemRemExpr rem |
result = rem and
arg = rem.getLeftOperand() and
rem.getRightOperand().(SemConstantIntegerExpr).getIntValue() = mod and
mod >= 2
)
or
exists(SemConstantIntegerExpr c |
mod = 2.pow([1 .. 30]) and
c.getIntValue() = mod - 1 and
result.(SemBitAndExpr).hasOperands(arg, c)
)
}
/**
* Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on
* its `testIsTrue` branch.
*/
private SemGuard moduloCheck(SemSsaVariable v, int val, int mod, boolean testIsTrue) {
exists(SemExpr rem, SemConstantIntegerExpr c, int r, boolean polarity |
result.isEquality(rem, c, polarity) and
c.getIntValue() = r and
rem = modExpr(v.getAUse(), mod) and
(
testIsTrue = polarity and val = r
or
testIsTrue = polarity.booleanNot() and
mod = 2 and
val = 1 - r and
(r = 0 or r = 1)
)
)
}
/**
* Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`.
*/
private predicate moduloGuardedRead(SemSsaVariable v, SemSsaReadPosition pos, int val, int mod) {
exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = moduloCheck(v, val, mod, testIsTrue) and
semGuardControlsSsaRead(guard, pos, testIsTrue)
)
}
/** Holds if `factor` is a power of 2 that divides `mask`. */
bindingset[mask]
private predicate andmaskFactor(int mask, int factor) {
mask % factor = 0 and
factor = 2.pow([1 .. 30])
}
/** Holds if `e` is evenly divisible by `factor`. */
private predicate evenlyDivisibleExpr(SemExpr e, int factor) {
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() |
e.(SemMulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2
or
e.(SemShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0
or
e.(SemBitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f))
)
}
/**
* Holds if `rix` is the number of input edges to `phi`.
*/
private predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
rix = max(int r | rankedPhiInput(phi, _, _, r))
}
/**
* Gets the remainder of `val` modulo `mod`.
*
* For `mod = 0` the result equals `val` and for `mod > 1` the result is within
* the range `[0 .. mod-1]`.
*/
bindingset[val, mod]
private int remainder(int val, int mod) {
mod = 0 and result = val
or
mod > 1 and result = ((val % mod) + mod) % mod
}
/**
* Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`.
*/
private predicate phiSelfModulus(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int mod
) {
exists(SemSsaBound phibound, int v, int m |
edge.phiInput(phi, inp) and
phibound.getAVariable() = phi and
ssaModulus(inp, edge, phibound, v, m) and
mod = m.gcd(v) and
mod != 1
)
}
/**
* Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`.
*/
private predicate phiModulusInit(SemSsaPhiNode phi, SemBound b, int val, int mod) {
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
edge.phiInput(phi, inp) and
ssaModulus(inp, edge, b, val, mod)
)
}
/**
* Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`.
*/
pragma[nomagic]
private predicate phiModulusRankStep(SemSsaPhiNode phi, SemBound b, int val, int mod, int rix) {
/*
* base case. If any phi input is equal to `b + val` modulo `mod`, that's a potential congruence
* class for the phi node.
module ModulusAnalysis<DeltaSig D, BoundSig<D> Bounds, UtilSig<D> U> {
/**
* Holds if `e + delta` equals `v` at `pos`.
*/
private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) {
U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v)
or
exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue)
)
}
rix = 0 and
phiModulusInit(phi, b, val, mod)
or
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int v1, int m1 |
mod != 1 and
val = remainder(v1, mod)
|
/**
* Holds if `add` is the addition of `larg` and `rarg`, neither of which are
* `ConstantIntegerExpr`s.
*/
private predicate nonConstAddition(SemExpr add, SemExpr larg, SemExpr rarg) {
exists(SemAddExpr a | a = add |
larg = a.getLeftOperand() and
rarg = a.getRightOperand()
) and
not larg instanceof SemConstantIntegerExpr and
not rarg instanceof SemConstantIntegerExpr
}
/**
* Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not
* a `ConstantIntegerExpr`.
*/
private predicate nonConstSubtraction(SemExpr sub, SemExpr larg, SemExpr rarg) {
exists(SemSubExpr s | s = sub |
larg = s.getLeftOperand() and
rarg = s.getRightOperand()
) and
not rarg instanceof SemConstantIntegerExpr
}
/** Gets an expression that is the remainder modulo `mod` of `arg`. */
private SemExpr modExpr(SemExpr arg, int mod) {
exists(SemRemExpr rem |
result = rem and
arg = rem.getLeftOperand() and
rem.getRightOperand().(SemConstantIntegerExpr).getIntValue() = mod and
mod >= 2
)
or
exists(SemConstantIntegerExpr c |
mod = 2.pow([1 .. 30]) and
c.getIntValue() = mod - 1 and
result.(SemBitAndExpr).hasOperands(arg, c)
)
}
/**
* Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on
* its `testIsTrue` branch.
*/
private SemGuard moduloCheck(SemSsaVariable v, int val, int mod, boolean testIsTrue) {
exists(SemExpr rem, SemConstantIntegerExpr c, int r, boolean polarity |
result.isEquality(rem, c, polarity) and
c.getIntValue() = r and
rem = modExpr(v.getAUse(), mod) and
(
testIsTrue = polarity and val = r
or
testIsTrue = polarity.booleanNot() and
mod = 2 and
val = 1 - r and
(r = 0 or r = 1)
)
)
}
/**
* Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`.
*/
private predicate moduloGuardedRead(SemSsaVariable v, SemSsaReadPosition pos, int val, int mod) {
exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = moduloCheck(v, val, mod, testIsTrue) and
semGuardControlsSsaRead(guard, pos, testIsTrue)
)
}
/** Holds if `factor` is a power of 2 that divides `mask`. */
bindingset[mask]
private predicate andmaskFactor(int mask, int factor) {
mask % factor = 0 and
factor = 2.pow([1 .. 30])
}
/** Holds if `e` is evenly divisible by `factor`. */
private predicate evenlyDivisibleExpr(SemExpr e, int factor) {
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() |
e.(SemMulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2
or
e.(SemShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0
or
e.(SemBitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f))
)
}
/**
* Holds if `rix` is the number of input edges to `phi`.
*/
private predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
rix = max(int r | rankedPhiInput(phi, _, _, r))
}
/**
* Gets the remainder of `val` modulo `mod`.
*
* For `mod = 0` the result equals `val` and for `mod > 1` the result is within
* the range `[0 .. mod-1]`.
*/
bindingset[val, mod]
private int remainder(int val, int mod) {
mod = 0 and result = val
or
mod > 1 and result = ((val % mod) + mod) % mod
}
/**
* Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`.
*/
private predicate phiSelfModulus(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int mod
) {
exists(Bounds::SemSsaBound phibound, int v, int m |
edge.phiInput(phi, inp) and
phibound.getAVariable() = phi and
ssaModulus(inp, edge, phibound, v, m) and
mod = m.gcd(v) and
mod != 1
)
}
/**
* Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`.
*/
private predicate phiModulusInit(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
edge.phiInput(phi, inp) and
ssaModulus(inp, edge, b, val, mod)
)
}
/**
* Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`.
*/
pragma[nomagic]
private predicate phiModulusRankStep(
SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod, int rix
) {
/*
* Recursive case. If `inp` = `b + v2` mod `m2`, we combine that with the preceding potential
* congruence class `b + v1` mod `m1`. The result will be the congruence class of `v1` modulo
* the greatest common denominator of `m1`, `m2`, and `v1 - v2`.
* base case. If any phi input is equal to `b + val` modulo `mod`, that's a potential congruence
* class for the phi node.
*/
exists(int v2, int m2 |
rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
ssaModulus(inp, edge, b, v2, m2) and
mod = m1.gcd(m2).gcd(v1 - v2)
rix = 0 and
phiModulusInit(phi, b, val, mod)
or
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int v1, int m1 |
mod != 1 and
val = remainder(v1, mod)
|
/*
* Recursive case. If `inp` = `b + v2` mod `m2`, we combine that with the preceding potential
* congruence class `b + v1` mod `m1`. The result will be the congruence class of `v1` modulo
* the greatest common denominator of `m1`, `m2`, and `v1 - v2`.
*/
exists(int v2, int m2 |
rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
ssaModulus(inp, edge, b, v2, m2) and
mod = m1.gcd(m2).gcd(v1 - v2)
)
or
/*
* Recursive case. If `inp` = `phi` mod `m2`, we combine that with the preceding potential
* congruence class `b + v1` mod `m1`. The result will be a congruence class modulo the greatest
* common denominator of `m1` and `m2`.
*/
exists(int m2 |
rankedPhiInput(phi, inp, edge, rix) and
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
phiSelfModulus(phi, inp, edge, m2) and
mod = m1.gcd(m2)
)
)
or
/*
* Recursive case. If `inp` = `phi` mod `m2`, we combine that with the preceding potential
* congruence class `b + v1` mod `m1`. The result will be a congruence class modulo the greatest
* common denominator of `m1` and `m2`.
*/
}
exists(int m2 |
rankedPhiInput(phi, inp, edge, rix) and
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
phiSelfModulus(phi, inp, edge, m2) and
mod = m1.gcd(m2)
/**
* Holds if `phi` is equal to `b + val` modulo `mod`.
*/
private predicate phiModulus(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
exists(int r |
maxPhiInputRank(phi, r) and
phiModulusRankStep(phi, b, val, mod, r)
)
)
}
}
/**
* Holds if `phi` is equal to `b + val` modulo `mod`.
*/
private predicate phiModulus(SemSsaPhiNode phi, SemBound b, int val, int mod) {
exists(int r |
maxPhiInputRank(phi, r) and
phiModulusRankStep(phi, b, val, mod, r)
)
}
/**
* Holds if `v` at `pos` is equal to `b + val` modulo `mod`.
*/
private predicate ssaModulus(SemSsaVariable v, SemSsaReadPosition pos, SemBound b, int val, int mod) {
phiModulus(v, b, val, mod) and pos.hasReadOfVar(v)
or
b.(SemSsaBound).getAVariable() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0
or
exists(SemExpr e, int val0, int delta |
semExprModulus(e, b, val0, mod) and
valueFlowStepSsa(v, pos, e, delta) and
val = remainder(val0 + delta, mod)
)
or
moduloGuardedRead(v, pos, val, mod) and b instanceof SemZeroBound
}
/**
* Holds if `e` is equal to `b + val` modulo `mod`.
*
* There are two cases for the modulus:
* - `mod = 0`: The equality `e = b + val` is an ordinary equality.
* - `mod > 1`: `val` lies within the range `[0 .. mod-1]`.
*/
cached
predicate semExprModulus(SemExpr e, SemBound b, int val, int mod) {
not ignoreExprModulus(e) and
(
e = b.getExpr(val) and mod = 0
/**
* Holds if `v` at `pos` is equal to `b + val` modulo `mod`.
*/
private predicate ssaModulus(
SemSsaVariable v, SemSsaReadPosition pos, Bounds::SemBound b, int val, int mod
) {
phiModulus(v, b, val, mod) and pos.hasReadOfVar(v)
or
evenlyDivisibleExpr(e, mod) and
val = 0 and
b instanceof SemZeroBound
b.(Bounds::SemSsaBound).getAVariable() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0
or
exists(SemSsaVariable v, SemSsaReadPositionBlock bb |
ssaModulus(v, bb, b, val, mod) and
e = v.getAUse() and
bb.getAnExpr() = e
)
or
exists(SemExpr mid, int val0, int delta |
semExprModulus(mid, b, val0, mod) and
semValueFlowStep(e, mid, delta) and
exists(SemExpr e, int val0, int delta |
semExprModulus(e, b, val0, mod) and
valueFlowStepSsa(v, pos, e, delta) and
val = remainder(val0 + delta, mod)
)
or
exists(SemConditionalExpr cond, int v1, int v2, int m1, int m2 |
cond = e and
condExprBranchModulus(cond, true, b, v1, m1) and
condExprBranchModulus(cond, false, b, v2, m2) and
mod = m1.gcd(m2).gcd(v1 - v2) and
mod != 1 and
val = remainder(v1, mod)
)
or
exists(SemBound b1, SemBound b2, int v1, int v2, int m1, int m2 |
addModulus(e, true, b1, v1, m1) and
addModulus(e, false, b2, v2, m2) and
mod = m1.gcd(m2) and
mod != 1 and
val = remainder(v1 + v2, mod)
|
b = b1 and b2 instanceof SemZeroBound
moduloGuardedRead(v, pos, val, mod) and b instanceof Bounds::SemZeroBound
}
/**
* Holds if `e` is equal to `b + val` modulo `mod`.
*
* There are two cases for the modulus:
* - `mod = 0`: The equality `e = b + val` is an ordinary equality.
* - `mod > 1`: `val` lies within the range `[0 .. mod-1]`.
*/
cached
predicate semExprModulus(SemExpr e, Bounds::SemBound b, int val, int mod) {
not ignoreExprModulus(e) and
(
e = b.getExpr(D::fromInt(val)) and mod = 0
or
b = b2 and b1 instanceof SemZeroBound
evenlyDivisibleExpr(e, mod) and
val = 0 and
b instanceof Bounds::SemZeroBound
or
exists(SemSsaVariable v, SemSsaReadPositionBlock bb |
ssaModulus(v, bb, b, val, mod) and
e = v.getAUse() and
bb.getAnExpr() = e
)
or
exists(SemExpr mid, int val0, int delta |
semExprModulus(mid, b, val0, mod) and
U::semValueFlowStep(e, mid, D::fromInt(delta)) and
val = remainder(val0 + delta, mod)
)
or
exists(SemConditionalExpr cond, int v1, int v2, int m1, int m2 |
cond = e and
condExprBranchModulus(cond, true, b, v1, m1) and
condExprBranchModulus(cond, false, b, v2, m2) and
mod = m1.gcd(m2).gcd(v1 - v2) and
mod != 1 and
val = remainder(v1, mod)
)
or
exists(Bounds::SemBound b1, Bounds::SemBound b2, int v1, int v2, int m1, int m2 |
addModulus(e, true, b1, v1, m1) and
addModulus(e, false, b2, v2, m2) and
mod = m1.gcd(m2) and
mod != 1 and
val = remainder(v1 + v2, mod)
|
b = b1 and b2 instanceof Bounds::SemZeroBound
or
b = b2 and b1 instanceof Bounds::SemZeroBound
)
or
exists(int v1, int v2, int m1, int m2 |
subModulus(e, true, b, v1, m1) and
subModulus(e, false, any(Bounds::SemZeroBound zb), v2, m2) and
mod = m1.gcd(m2) and
mod != 1 and
val = remainder(v1 - v2, mod)
)
)
or
exists(int v1, int v2, int m1, int m2 |
subModulus(e, true, b, v1, m1) and
subModulus(e, false, any(SemZeroBound zb), v2, m2) and
mod = m1.gcd(m2) and
mod != 1 and
val = remainder(v1 - v2, mod)
}
private predicate condExprBranchModulus(
SemConditionalExpr cond, boolean branch, Bounds::SemBound b, int val, int mod
) {
semExprModulus(cond.getBranchExpr(branch), b, val, mod)
}
private predicate addModulus(SemExpr add, boolean isLeft, Bounds::SemBound b, int val, int mod) {
exists(SemExpr larg, SemExpr rarg | nonConstAddition(add, larg, rarg) |
semExprModulus(larg, b, val, mod) and isLeft = true
or
semExprModulus(rarg, b, val, mod) and isLeft = false
)
)
}
}
private predicate condExprBranchModulus(
SemConditionalExpr cond, boolean branch, SemBound b, int val, int mod
) {
semExprModulus(cond.getBranchExpr(branch), b, val, mod)
}
private predicate addModulus(SemExpr add, boolean isLeft, SemBound b, int val, int mod) {
exists(SemExpr larg, SemExpr rarg | nonConstAddition(add, larg, rarg) |
semExprModulus(larg, b, val, mod) and isLeft = true
or
semExprModulus(rarg, b, val, mod) and isLeft = false
)
}
private predicate subModulus(SemExpr sub, boolean isLeft, SemBound b, int val, int mod) {
exists(SemExpr larg, SemExpr rarg | nonConstSubtraction(sub, larg, rarg) |
semExprModulus(larg, b, val, mod) and isLeft = true
or
semExprModulus(rarg, b, val, mod) and isLeft = false
)
}
/**
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
* in an arbitrary 1-based numbering of the input edges to `phi`.
*/
private predicate rankedPhiInput(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
) {
edge.phiInput(phi, inp) and
edge =
rank[r](SemSsaReadPositionPhiInputEdge e |
e.phiInput(phi, _)
|
e order by e.getOrigBlock().getUniqueId()
private predicate subModulus(SemExpr sub, boolean isLeft, Bounds::SemBound b, int val, int mod) {
exists(SemExpr larg, SemExpr rarg | nonConstSubtraction(sub, larg, rarg) |
semExprModulus(larg, b, val, mod) and isLeft = true
or
semExprModulus(rarg, b, val, mod) and isLeft = false
)
}
/**
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
* in an arbitrary 1-based numbering of the input edges to `phi`.
*/
private predicate rankedPhiInput(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
) {
edge.phiInput(phi, inp) and
edge =
rank[r](SemSsaReadPositionPhiInputEdge e |
e.phiInput(phi, _)
|
e order by e.getOrigBlock().getUniqueId()
)
}
}

View File

@@ -1,832 +1,24 @@
/**
* Provides classes and predicates for range analysis.
*
* An inferred bound can either be a specific integer, the abstract value of an
* SSA variable, or the abstract value of an interesting expression. The latter
* category includes array lengths that are not SSA variables.
*
* If an inferred bound relies directly on a condition, then this condition is
* reported as the reason for the bound.
*/
/*
* This library tackles range analysis as a flow problem. Consider e.g.:
* ```
* len = arr.length;
* if (x < len) { ... y = x-1; ... y ... }
* ```
* In this case we would like to infer `y <= arr.length - 2`, and this is
* accomplished by tracking the bound through a sequence of steps:
* ```
* arr.length --> len = .. --> x < len --> x-1 --> y = .. --> y
* ```
*
* In its simplest form the step relation `E1 --> E2` relates two expressions
* such that `E1 <= B` implies `E2 <= B` for any `B` (with a second separate
* step relation handling lower bounds). Examples of such steps include
* assignments `E2 = E1` and conditions `x <= E1` where `E2` is a use of `x`
* guarded by the condition.
*
* In order to handle subtractions and additions with constants, and strict
* comparisons, the step relation is augmented with an integer delta. With this
* generalization `E1 --(delta)--> E2` relates two expressions and an integer
* such that `E1 <= B` implies `E2 <= B + delta` for any `B`. This corresponds
* to the predicate `boundFlowStep`.
*
* The complete range analysis is then implemented as the transitive closure of
* the step relation summing the deltas along the way. If `E1` transitively
* steps to `E2`, `delta` is the sum of deltas along the path, and `B` is an
* interesting bound equal to the value of `E1` then `E2 <= B + delta`. This
* corresponds to the predicate `bounded`.
*
* Phi nodes need a little bit of extra handling. Consider `x0 = phi(x1, x2)`.
* There are essentially two cases:
* - If `x1 <= B + d1` and `x2 <= B + d2` then `x0 <= B + max(d1,d2)`.
* - If `x1 <= B + d1` and `x2 <= x0 + d2` with `d2 <= 0` then `x0 <= B + d1`.
* The first case is for whenever a bound can be proven without taking looping
* into account. The second case is relevant when `x2` comes from a back-edge
* where we can prove that the variable has been non-increasing through the
* loop-iteration as this means that any upper bound that holds prior to the
* loop also holds for the variable during the loop.
* This generalizes to a phi node with `n` inputs, so if
* `x0 = phi(x1, ..., xn)` and `xi <= B + delta` for one of the inputs, then we
* also have `x0 <= B + delta` if we can prove either:
* - `xj <= B + d` with `d <= delta` or
* - `xj <= x0 + d` with `d <= 0`
* for each input `xj`.
*
* As all inferred bounds can be related directly to a path in the source code
* the only source of non-termination is if successive redundant (and thereby
* increasingly worse) bounds are calculated along a loop in the source code.
* We prevent this by weakening the bound to a small finite set of bounds when
* a path follows a second back-edge (we postpone weakening till the second
* back-edge as a precise bound might require traversing a loop once).
*/
private import RangeAnalysisSpecific as Specific
private import RangeAnalysisStage
private import RangeAnalysisSpecific
private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
private import RangeUtils
private import SignAnalysisCommon
private import ModulusAnalysis
private import experimental.semmle.code.cpp.semantic.Semantic
private import ConstantAnalysis
private import experimental.semmle.code.cpp.semantic.SemanticBound as SemanticBound
cached
private module RangeAnalysisCache {
cached
module RangeAnalysisPublic {
/**
* Holds if `b + delta` is a valid bound for `e`.
* - `upper = true` : `e <= b + delta`
* - `upper = false` : `e >= b + delta`
*
* The reason for the bound is given by `reason` and may be either a condition
* or `NoReason` if the bound was proven directly without the use of a bounding
* condition.
*/
cached
predicate semBounded(SemExpr e, SemBound b, int delta, boolean upper, SemReason reason) {
bounded(e, b, delta, upper, _, _, reason) and
bestBound(e, b, delta, upper)
}
module Bounds implements BoundSig<FloatDelta> {
class SemBound instanceof SemanticBound::SemBound {
string toString() { result = super.toString() }
SemExpr getExpr(float delta) { result = super.getExpr(delta) }
}
/**
* Holds if `guard = boundFlowCond(_, _, _, _, _) or guard = eqFlowCond(_, _, _, _, _)`.
*/
cached
predicate possibleReason(SemGuard guard) {
guard = boundFlowCond(_, _, _, _, _) or guard = semEqFlowCond(_, _, _, _, _)
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
}
}
private import RangeAnalysisCache
import RangeAnalysisPublic
private module CppRangeAnalysis =
RangeStage<FloatDelta, Bounds, CppLangImpl, RangeUtil<FloatDelta, CppLangImpl>>;
/**
* Holds if `b + delta` is a valid bound for `e` and this is the best such delta.
* - `upper = true` : `e <= b + delta`
* - `upper = false` : `e >= b + delta`
*/
private predicate bestBound(SemExpr e, SemBound b, int delta, boolean upper) {
delta = min(int d | bounded(e, b, d, upper, _, _, _)) and upper = true
or
delta = max(int d | bounded(e, b, d, upper, _, _, _)) and upper = false
}
/**
* Holds if `comp` corresponds to:
* - `upper = true` : `v <= e + delta` or `v < e + delta`
* - `upper = false` : `v >= e + delta` or `v > e + delta`
*/
private predicate boundCondition(
SemRelationalExpr comp, SemSsaVariable v, SemExpr e, int delta, boolean upper
) {
comp.getLesserOperand() = semSsaRead(v, delta) and e = comp.getGreaterOperand() and upper = true
or
comp.getGreaterOperand() = semSsaRead(v, delta) and e = comp.getLesserOperand() and upper = false
or
exists(SemSubExpr sub, SemConstantIntegerExpr c, int d |
// (v - d) - e < c
comp.getLesserOperand() = sub and
comp.getGreaterOperand() = c and
sub.getLeftOperand() = semSsaRead(v, d) and
sub.getRightOperand() = e and
upper = true and
delta = d + c.getIntValue()
or
// (v - d) - e > c
comp.getGreaterOperand() = sub and
comp.getLesserOperand() = c and
sub.getLeftOperand() = semSsaRead(v, d) and
sub.getRightOperand() = e and
upper = false and
delta = d + c.getIntValue()
or
// e - (v - d) < c
comp.getLesserOperand() = sub and
comp.getGreaterOperand() = c and
sub.getLeftOperand() = e and
sub.getRightOperand() = semSsaRead(v, d) and
upper = false and
delta = d - c.getIntValue()
or
// e - (v - d) > c
comp.getGreaterOperand() = sub and
comp.getLesserOperand() = c and
sub.getLeftOperand() = e and
sub.getRightOperand() = semSsaRead(v, d) and
upper = true and
delta = d - c.getIntValue()
)
}
/**
* Holds if `comp` is a comparison between `x` and `y` for which `y - x` has a
* fixed value modulo some `mod > 1`, such that the comparison can be
* strengthened by `strengthen` when evaluating to `testIsTrue`.
*/
private predicate modulusComparison(SemRelationalExpr comp, boolean testIsTrue, int strengthen) {
exists(
SemBound b, int v1, int v2, int mod1, int mod2, int mod, boolean resultIsStrict, int d, int k
|
// If `x <= y` and `x =(mod) b + v1` and `y =(mod) b + v2` then
// `0 <= y - x =(mod) v2 - v1`. By choosing `k =(mod) v2 - v1` with
// `0 <= k < mod` we get `k <= y - x`. If the resulting comparison is
// strict then the strengthening amount is instead `k - 1` modulo `mod`:
// `x < y` means `0 <= y - x - 1 =(mod) k - 1` so `k - 1 <= y - x - 1` and
// thus `k - 1 < y - x` with `0 <= k - 1 < mod`.
semExprModulus(comp.getLesserOperand(), b, v1, mod1) and
semExprModulus(comp.getGreaterOperand(), b, v2, mod2) and
mod = mod1.gcd(mod2) and
mod != 1 and
(testIsTrue = true or testIsTrue = false) and
(
if comp.isStrict()
then resultIsStrict = testIsTrue
else resultIsStrict = testIsTrue.booleanNot()
) and
(
resultIsStrict = true and d = 1
or
resultIsStrict = false and d = 0
) and
(
testIsTrue = true and k = v2 - v1
or
testIsTrue = false and k = v1 - v2
) and
strengthen = (((k - d) % mod) + mod) % mod
)
}
/**
* Gets a condition that tests whether `v` is bounded by `e + delta`.
*
* If the condition evaluates to `testIsTrue`:
* - `upper = true` : `v <= e + delta`
* - `upper = false` : `v >= e + delta`
*/
private SemGuard boundFlowCond(
SemSsaVariable v, SemExpr e, int delta, boolean upper, boolean testIsTrue
) {
exists(
SemRelationalExpr comp, int d1, int d2, int d3, int strengthen, boolean compIsUpper,
boolean resultIsStrict
|
comp = result.asExpr() and
boundCondition(comp, v, e, d1, compIsUpper) and
(testIsTrue = true or testIsTrue = false) and
upper = compIsUpper.booleanXor(testIsTrue.booleanNot()) and
(
if comp.isStrict()
then resultIsStrict = testIsTrue
else resultIsStrict = testIsTrue.booleanNot()
) and
(
if
getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or
getTrackedTypeForSsaVariable(v) instanceof SemAddressType
then
upper = true and strengthen = -1
or
upper = false and strengthen = 1
else strengthen = 0
) and
(
exists(int k | modulusComparison(comp, testIsTrue, k) and d2 = strengthen * k)
or
not modulusComparison(comp, testIsTrue, _) and d2 = 0
) and
// A strict inequality `x < y` can be strengthened to `x <= y - 1`.
(
resultIsStrict = true and d3 = strengthen
or
resultIsStrict = false and d3 = 0
) and
delta = d1 + d2 + d3
)
or
exists(boolean testIsTrue0 |
semImplies_v2(result, testIsTrue, boundFlowCond(v, e, delta, upper, testIsTrue0), testIsTrue0)
)
or
result = semEqFlowCond(v, e, delta, true, testIsTrue) and
(upper = true or upper = false)
or
// guard that tests whether `v2` is bounded by `e + delta + d1 - d2` and
// exists a guard `guardEq` such that `v = v2 - d1 + d2`.
exists(SemSsaVariable v2, SemGuard guardEq, boolean eqIsTrue, int d1, int d2 |
guardEq = semEqFlowCond(v, semSsaRead(v2, d1), d2, true, eqIsTrue) and
result = boundFlowCond(v2, e, delta + d1 - d2, upper, testIsTrue) and
// guardEq needs to control guard
guardEq.directlyControls(result.getBasicBlock(), eqIsTrue)
)
}
private newtype TSemReason =
TSemNoReason() or
TSemCondReason(SemGuard guard) { possibleReason(guard) }
/**
* A reason for an inferred bound. This can either be `CondReason` if the bound
* is due to a specific condition, or `NoReason` if the bound is inferred
* without going through a bounding condition.
*/
abstract class SemReason extends TSemReason {
/** Gets a textual representation of this reason. */
abstract string toString();
}
/**
* A reason for an inferred bound that indicates that the bound is inferred
* without going through a bounding condition.
*/
class SemNoReason extends SemReason, TSemNoReason {
override string toString() { result = "NoReason" }
}
/** A reason for an inferred bound pointing to a condition. */
class SemCondReason extends SemReason, TSemCondReason {
/** Gets the condition that is the reason for the bound. */
SemGuard getCond() { this = TSemCondReason(result) }
override string toString() { result = getCond().toString() }
}
/**
* Holds if `e + delta` is a valid bound for `v` at `pos`.
* - `upper = true` : `v <= e + delta`
* - `upper = false` : `v >= e + delta`
*/
private predicate boundFlowStepSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta, boolean upper, SemReason reason
) {
semSsaUpdateStep(v, e, delta) and
pos.hasReadOfVar(v) and
(upper = true or upper = false) and
reason = TSemNoReason()
or
exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = boundFlowCond(v, e, delta, upper, testIsTrue) and
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
reason = TSemCondReason(guard)
)
}
/** Holds if `v != e + delta` at `pos` and `v` is of integral type. */
private predicate unequalFlowStepIntegralSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta, SemReason reason
) {
getTrackedTypeForSsaVariable(v) instanceof SemIntegerType and
exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = semEqFlowCond(v, e, delta, false, testIsTrue) and
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
reason = TSemCondReason(guard)
)
}
/**
* An expression that does conversion, boxing, or unboxing
*/
private class ConvertOrBoxExpr extends SemUnaryExpr {
ConvertOrBoxExpr() {
this instanceof SemConvertExpr
or
this instanceof SemBoxExpr
or
this instanceof SemUnboxExpr
}
}
/**
* A cast that can be ignored for the purpose of range analysis.
*/
private class SafeCastExpr extends ConvertOrBoxExpr {
SafeCastExpr() {
conversionCannotOverflow(getTrackedType(pragma[only_bind_into](getOperand())),
getTrackedType(this))
}
}
/**
* Holds if `typ` is a small integral type with the given lower and upper bounds.
*/
private predicate typeBound(SemIntegerType typ, int lowerbound, int upperbound) {
exists(int bitSize | bitSize = typ.getByteSize() * 8 |
bitSize < 32 and
(
if typ.isSigned()
then (
upperbound = 1.bitShiftLeft(bitSize - 1) - 1 and
lowerbound = -upperbound - 1
) else (
lowerbound = 0 and
upperbound = 1.bitShiftLeft(bitSize) - 1
)
)
)
}
/**
* A cast to a small integral type that may overflow or underflow.
*/
private class NarrowingCastExpr extends ConvertOrBoxExpr {
NarrowingCastExpr() {
not this instanceof SafeCastExpr and
typeBound(getTrackedType(this), _, _)
}
/** Gets the lower bound of the resulting type. */
int getLowerBound() { typeBound(getTrackedType(this), result, _) }
/** Gets the upper bound of the resulting type. */
int getUpperBound() { typeBound(getTrackedType(this), _, result) }
}
/** Holds if `e >= 1` as determined by sign analysis. */
private predicate strictlyPositiveIntegralExpr(SemExpr e) {
semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType
}
/** Holds if `e <= -1` as determined by sign analysis. */
private predicate strictlyNegativeIntegralExpr(SemExpr e) {
semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType
}
/**
* Holds if `e1 + delta` is a valid bound for `e2`.
* - `upper = true` : `e2 <= e1 + delta`
* - `upper = false` : `e2 >= e1 + delta`
*/
private predicate boundFlowStep(SemExpr e2, SemExpr e1, int delta, boolean upper) {
semValueFlowStep(e2, e1, delta) and
(upper = true or upper = false)
or
e2.(SafeCastExpr).getOperand() = e1 and
delta = 0 and
(upper = true or upper = false)
or
exists(SemExpr x | e2.(SemAddExpr).hasOperands(e1, x) |
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
not x instanceof SemConstantIntegerExpr and
not e1 instanceof SemConstantIntegerExpr and
if strictlyPositiveIntegralExpr(x)
then upper = false and delta = 1
else
if semPositive(x)
then upper = false and delta = 0
else
if strictlyNegativeIntegralExpr(x)
then upper = true and delta = -1
else
if semNegative(x)
then upper = true and delta = 0
else none()
)
or
exists(SemExpr x, SemSubExpr sub |
e2 = sub and
sub.getLeftOperand() = e1 and
sub.getRightOperand() = x
|
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
not x instanceof SemConstantIntegerExpr and
if strictlyPositiveIntegralExpr(x)
then upper = true and delta = -1
else
if semPositive(x)
then upper = true and delta = 0
else
if strictlyNegativeIntegralExpr(x)
then upper = false and delta = 1
else
if semNegative(x)
then upper = false and delta = 0
else none()
)
or
e2.(SemRemExpr).getRightOperand() = e1 and
semPositive(e1) and
delta = -1 and
upper = true
or
e2.(SemRemExpr).getLeftOperand() = e1 and semPositive(e1) and delta = 0 and upper = true
or
e2.(SemBitAndExpr).getAnOperand() = e1 and
semPositive(e1) and
delta = 0 and
upper = true
or
e2.(SemBitOrExpr).getAnOperand() = e1 and
semPositive(e2) and
delta = 0 and
upper = false
or
Specific::hasBound(e2, e1, delta, upper)
}
/** Holds if `e2 = e1 * factor` and `factor > 0`. */
private predicate boundFlowStepMul(SemExpr e2, SemExpr e1, int factor) {
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 |
e2.(SemMulExpr).hasOperands(e1, c) and factor = k
or
exists(SemShiftLeftExpr e |
e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = 2.pow(k)
)
)
}
/**
* Holds if `e2 = e1 / factor` and `factor > 0`.
*
* This conflates division, right shift, and unsigned right shift and is
* therefore only valid for non-negative numbers.
*/
private predicate boundFlowStepDiv(SemExpr e2, SemExpr e1, int factor) {
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 |
exists(SemDivExpr e |
e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = k
)
or
exists(SemShiftRightExpr e |
e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = 2.pow(k)
)
or
exists(SemShiftRightUnsignedExpr e |
e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = 2.pow(k)
)
)
}
/**
* Holds if `b + delta` is a valid bound for `v` at `pos`.
* - `upper = true` : `v <= b + delta`
* - `upper = false` : `v >= b + delta`
*/
private predicate boundedSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemBound b, int delta, boolean upper,
boolean fromBackEdge, int origdelta, SemReason reason
) {
exists(SemExpr mid, int d1, int d2, SemReason r1, SemReason r2 |
boundFlowStepSsa(v, pos, mid, d1, upper, r1) and
bounded(mid, b, d2, upper, fromBackEdge, origdelta, r2) and
// upper = true: v <= mid + d1 <= b + d1 + d2 = b + delta
// upper = false: v >= mid + d1 >= b + d1 + d2 = b + delta
delta = d1 + d2 and
(if r1 instanceof SemNoReason then reason = r2 else reason = r1)
)
or
exists(int d, SemReason r1, SemReason r2 |
boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or
boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2)
|
unequalIntegralSsa(v, pos, b, d, r1) and
(
upper = true and delta = d - 1
or
upper = false and delta = d + 1
) and
(
reason = r1
or
reason = r2 and not r2 instanceof SemNoReason
)
)
}
/**
* Holds if `v != b + delta` at `pos` and `v` is of integral type.
*/
private predicate unequalIntegralSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemBound b, int delta, SemReason reason
) {
exists(SemExpr e, int d1, int d2 |
unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and
boundedUpper(e, b, d1) and
boundedLower(e, b, d2) and
delta = d2 + d1
)
}
/**
* Holds if `b + delta` is an upper bound for `e`.
*
* This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`.
*/
pragma[nomagic]
private predicate boundedUpper(SemExpr e, SemBound b, int delta) {
bounded(e, b, delta, true, _, _, _)
}
/**
* Holds if `b + delta` is a lower bound for `e`.
*
* This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`.
*/
pragma[nomagic]
private predicate boundedLower(SemExpr e, SemBound b, int delta) {
bounded(e, b, delta, false, _, _, _)
}
/** Weakens a delta to lie in the range `[-1..1]`. */
bindingset[delta, upper]
private int weakenDelta(boolean upper, int delta) {
delta in [-1 .. 1] and result = delta
or
upper = true and result = -1 and delta < -1
or
upper = false and result = 1 and delta > 1
}
/**
* Holds if `b + delta` is a valid bound for `inp` when used as an input to
* `phi` along `edge`.
* - `upper = true` : `inp <= b + delta`
* - `upper = false` : `inp >= b + delta`
*/
private predicate boundedPhiInp(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, SemBound b, int delta,
boolean upper, boolean fromBackEdge, int origdelta, SemReason reason
) {
edge.phiInput(phi, inp) and
exists(int d, boolean fromBackEdge0 |
boundedSsa(inp, edge, b, d, upper, fromBackEdge0, origdelta, reason)
or
boundedPhi(inp, b, d, upper, fromBackEdge0, origdelta, reason)
or
b.(SemSsaBound).getAVariable() = inp and
d = 0 and
(upper = true or upper = false) and
fromBackEdge0 = false and
origdelta = 0 and
reason = TSemNoReason()
|
if semBackEdge(phi, inp, edge)
then
fromBackEdge = true and
(
fromBackEdge0 = true and delta = weakenDelta(upper, d - origdelta) + origdelta
or
fromBackEdge0 = false and delta = d
)
else (
delta = d and fromBackEdge = fromBackEdge0
)
)
}
/**
* Holds if `b + delta` is a valid bound for `inp` when used as an input to
* `phi` along `edge`.
* - `upper = true` : `inp <= b + delta`
* - `upper = false` : `inp >= b + delta`
*
* Equivalent to `boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _)`.
*/
pragma[noinline]
private predicate boundedPhiInp1(
SemSsaPhiNode phi, SemBound b, boolean upper, SemSsaVariable inp,
SemSsaReadPositionPhiInputEdge edge, int delta
) {
boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _)
}
/**
* Holds if `phi` is a valid bound for `inp` when used as an input to `phi`
* along `edge`.
* - `upper = true` : `inp <= phi`
* - `upper = false` : `inp >= phi`
*/
private predicate selfBoundedPhiInp(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, boolean upper
) {
exists(int d, SemSsaBound phibound |
phibound.getAVariable() = phi and
boundedPhiInp(phi, inp, edge, phibound, d, upper, _, _, _) and
(
upper = true and d <= 0
or
upper = false and d >= 0
)
)
}
/**
* Holds if `b + delta` is a valid bound for some input, `inp`, to `phi`, and
* thus a candidate bound for `phi`.
* - `upper = true` : `inp <= b + delta`
* - `upper = false` : `inp >= b + delta`
*/
pragma[noinline]
private predicate boundedPhiCand(
SemSsaPhiNode phi, boolean upper, SemBound b, int delta, boolean fromBackEdge, int origdelta,
SemReason reason
) {
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
boundedPhiInp(phi, inp, edge, b, delta, upper, fromBackEdge, origdelta, reason)
)
}
/**
* Holds if the candidate bound `b + delta` for `phi` is valid for the phi input
* `inp` along `edge`.
*/
private predicate boundedPhiCandValidForEdge(
SemSsaPhiNode phi, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta,
SemReason reason, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge
) {
boundedPhiCand(phi, upper, b, delta, fromBackEdge, origdelta, reason) and
(
exists(int d | boundedPhiInp1(phi, b, upper, inp, edge, d) | upper = true and d <= delta)
or
exists(int d | boundedPhiInp1(phi, b, upper, inp, edge, d) | upper = false and d >= delta)
or
selfBoundedPhiInp(phi, inp, edge, upper)
)
}
/**
* Holds if `b + delta` is a valid bound for `phi`.
* - `upper = true` : `phi <= b + delta`
* - `upper = false` : `phi >= b + delta`
*/
private predicate boundedPhi(
SemSsaPhiNode phi, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta,
SemReason reason
) {
forex(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | edge.phiInput(phi, inp) |
boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge)
)
}
/**
* Holds if `e` has an upper (for `upper = true`) or lower
* (for `upper = false`) bound of `b`.
*/
private predicate baseBound(SemExpr e, int b, boolean upper) {
Specific::hasConstantBound(e, b, upper)
or
upper = false and
b = 0 and
semPositive(e.(SemBitAndExpr).getAnOperand()) and
// REVIEW: We let the language opt out here to preserve original results.
not Specific::ignoreZeroLowerBound(e)
}
/**
* Holds if the value being cast has an upper (for `upper = true`) or lower
* (for `upper = false`) bound within the bounds of the resulting type.
* For `upper = true` this means that the cast will not overflow and for
* `upper = false` this means that the cast will not underflow.
*/
private predicate safeNarrowingCast(NarrowingCastExpr cast, boolean upper) {
exists(int bound | bounded(cast.getOperand(), any(SemZeroBound zb), bound, upper, _, _, _) |
upper = true and bound <= cast.getUpperBound()
or
upper = false and bound >= cast.getLowerBound()
)
}
pragma[noinline]
private predicate boundedCastExpr(
NarrowingCastExpr cast, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta,
SemReason reason
) {
bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
}
/**
* Holds if `b + delta` is a valid bound for `e`.
* - `upper = true` : `e <= b + delta`
* - `upper = false` : `e >= b + delta`
*/
private predicate bounded(
SemExpr e, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta,
SemReason reason
) {
not Specific::ignoreExprBound(e) and
(
e = b.getExpr(delta) and
(upper = true or upper = false) and
fromBackEdge = false and
origdelta = delta and
reason = TSemNoReason()
or
baseBound(e, delta, upper) and
b instanceof SemZeroBound and
fromBackEdge = false and
origdelta = delta and
reason = TSemNoReason()
or
exists(SemSsaVariable v, SemSsaReadPositionBlock bb |
boundedSsa(v, bb, b, delta, upper, fromBackEdge, origdelta, reason) and
e = v.getAUse() and
bb.getBlock() = e.getBasicBlock()
)
or
exists(SemExpr mid, int d1, int d2 |
boundFlowStep(e, mid, d1, upper) and
// Constants have easy, base-case bounds, so let's not infer any recursive bounds.
not e instanceof SemConstantIntegerExpr and
bounded(mid, b, d2, upper, fromBackEdge, origdelta, reason) and
// upper = true: e <= mid + d1 <= b + d1 + d2 = b + delta
// upper = false: e >= mid + d1 >= b + d1 + d2 = b + delta
delta = d1 + d2
)
or
exists(SemSsaPhiNode phi |
boundedPhi(phi, b, delta, upper, fromBackEdge, origdelta, reason) and
e = phi.getAUse()
)
or
exists(SemExpr mid, int factor, int d |
boundFlowStepMul(e, mid, factor) and
not e instanceof SemConstantIntegerExpr and
bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and
b instanceof SemZeroBound and
delta = d * factor
)
or
exists(SemExpr mid, int factor, int d |
boundFlowStepDiv(e, mid, factor) and
not e instanceof SemConstantIntegerExpr and
bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and
b instanceof SemZeroBound and
d >= 0 and
delta = d / factor
)
or
exists(NarrowingCastExpr cast |
cast = e and
safeNarrowingCast(cast, upper.booleanNot()) and
boundedCastExpr(cast, b, delta, upper, fromBackEdge, origdelta, reason)
)
or
exists(
SemConditionalExpr cond, int d1, int d2, boolean fbe1, boolean fbe2, int od1, int od2,
SemReason r1, SemReason r2
|
cond = e and
boundedConditionalExpr(cond, b, upper, true, d1, fbe1, od1, r1) and
boundedConditionalExpr(cond, b, upper, false, d2, fbe2, od2, r2) and
(
delta = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1
or
delta = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2
)
|
upper = true and delta = d1.maximum(d2)
or
upper = false and delta = d1.minimum(d2)
)
)
}
private predicate boundedConditionalExpr(
SemConditionalExpr cond, SemBound b, boolean upper, boolean branch, int delta,
boolean fromBackEdge, int origdelta, SemReason reason
) {
bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason)
}
import CppRangeAnalysis

View File

@@ -3,86 +3,90 @@
*/
private import experimental.semmle.code.cpp.semantic.Semantic
private import RangeAnalysisStage
private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
/**
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreSsaReadCopy(SemExpr e) { none() }
module CppLangImpl implements LangSig<FloatDelta> {
/**
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreSsaReadCopy(SemExpr e) { none() }
/**
* Ignore the bound on this expression.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreExprBound(SemExpr e) { none() }
/**
* Ignore the bound on this expression.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreExprBound(SemExpr e) { none() }
/**
* Ignore any inferred zero lower bound on this expression.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreZeroLowerBound(SemExpr e) { none() }
/**
* Ignore any inferred zero lower bound on this expression.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreZeroLowerBound(SemExpr e) { none() }
/**
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreSsaReadArithmeticExpr(SemExpr e) { none() }
/**
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreSsaReadArithmeticExpr(SemExpr e) { none() }
/**
* Holds if the specified variable should be excluded from the result of `ssaRead()`.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreSsaReadAssignment(SemSsaVariable v) { none() }
/**
* Holds if the specified variable should be excluded from the result of `ssaRead()`.
*
* This predicate is to keep the results identical to the original Java implementation. It should be
* removed once we have the new implementation matching the old results exactly.
*/
predicate ignoreSsaReadAssignment(SemSsaVariable v) { none() }
/**
* Adds additional results to `ssaRead()` that are specific to Java.
*
* This predicate handles propagation of offsets for post-increment and post-decrement expressions
* in exactly the same way as the old Java implementation. Once the new implementation matches the
* old one, we should remove this predicate and propagate deltas for all similar patterns, whether
* or not they come from a post-increment/decrement expression.
*/
SemExpr specificSsaRead(SemSsaVariable v, int delta) { none() }
/**
* Adds additional results to `ssaRead()` that are specific to Java.
*
* This predicate handles propagation of offsets for post-increment and post-decrement expressions
* in exactly the same way as the old Java implementation. Once the new implementation matches the
* old one, we should remove this predicate and propagate deltas for all similar patterns, whether
* or not they come from a post-increment/decrement expression.
*/
SemExpr specificSsaRead(SemSsaVariable v, float delta) { none() }
/**
* Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`).
*/
predicate hasConstantBound(SemExpr e, int bound, boolean upper) { none() }
/**
* Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`).
*/
predicate hasConstantBound(SemExpr e, float bound, boolean upper) { none() }
/**
* Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`).
*/
predicate hasBound(SemExpr e, SemExpr bound, int delta, boolean upper) { none() }
/**
* Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`).
*/
predicate hasBound(SemExpr e, SemExpr bound, float delta, boolean upper) { none() }
/**
* Holds if the value of `dest` is known to be `src + delta`.
*/
predicate additionalValueFlowStep(SemExpr dest, SemExpr src, int delta) { none() }
/**
* Holds if the value of `dest` is known to be `src + delta`.
*/
predicate additionalValueFlowStep(SemExpr dest, SemExpr src, float delta) { none() }
/**
* Gets the type that range analysis should use to track the result of the specified expression,
* if a type other than the original type of the expression is to be used.
*
* This predicate is commonly used in languages that support immutable "boxed" types that are
* actually references but whose values can be tracked as the type contained in the box.
*/
SemType getAlternateType(SemExpr e) { none() }
/**
* Gets the type that range analysis should use to track the result of the specified expression,
* if a type other than the original type of the expression is to be used.
*
* This predicate is commonly used in languages that support immutable "boxed" types that are
* actually references but whose values can be tracked as the type contained in the box.
*/
SemType getAlternateType(SemExpr e) { none() }
/**
* Gets the type that range analysis should use to track the result of the specified source
* variable, if a type other than the original type of the expression is to be used.
*
* This predicate is commonly used in languages that support immutable "boxed" types that are
* actually references but whose values can be tracked as the type contained in the box.
*/
SemType getAlternateTypeForSsaVariable(SemSsaVariable var) { none() }
/**
* Gets the type that range analysis should use to track the result of the specified source
* variable, if a type other than the original type of the expression is to be used.
*
* This predicate is commonly used in languages that support immutable "boxed" types that are
* actually references but whose values can be tracked as the type contained in the box.
*/
SemType getAlternateTypeForSsaVariable(SemSsaVariable var) { none() }
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,133 +3,138 @@
*/
private import experimental.semmle.code.cpp.semantic.Semantic
private import RangeAnalysisSpecific as Specific
private import RangeAnalysisSpecific
private import RangeAnalysisStage as Range
private import ConstantAnalysis
/**
* Gets an expression that equals `v - d`.
*/
SemExpr semSsaRead(SemSsaVariable v, int delta) {
// There are various language-specific extension points that can be removed once we no longer
// expect to match the original Java implementation's results exactly.
result = v.getAUse() and delta = 0
or
exists(int d1, SemConstantIntegerExpr c |
result.(SemAddExpr).hasOperands(semSsaRead(v, d1), c) and
delta = d1 - c.getIntValue() and
not Specific::ignoreSsaReadArithmeticExpr(result)
)
or
exists(SemSubExpr sub, int d1, SemConstantIntegerExpr c |
result = sub and
sub.getLeftOperand() = semSsaRead(v, d1) and
sub.getRightOperand() = c and
delta = d1 + c.getIntValue() and
not Specific::ignoreSsaReadArithmeticExpr(result)
)
or
result = v.(SemSsaExplicitUpdate).getSourceExpr() and
delta = 0 and
not Specific::ignoreSsaReadAssignment(v)
or
result = Specific::specificSsaRead(v, delta)
or
result.(SemCopyValueExpr).getOperand() = semSsaRead(v, delta) and
not Specific::ignoreSsaReadCopy(result)
or
result.(SemStoreExpr).getOperand() = semSsaRead(v, delta)
}
/**
* Gets a condition that tests whether `v` equals `e + delta`.
*
* If the condition evaluates to `testIsTrue`:
* - `isEq = true` : `v == e + delta`
* - `isEq = false` : `v != e + delta`
*/
SemGuard semEqFlowCond(SemSsaVariable v, SemExpr e, int delta, boolean isEq, boolean testIsTrue) {
exists(boolean eqpolarity |
result.isEquality(semSsaRead(v, delta), e, eqpolarity) and
(testIsTrue = true or testIsTrue = false) and
eqpolarity.booleanXor(testIsTrue).booleanNot() = isEq
)
or
exists(boolean testIsTrue0 |
semImplies_v2(result, testIsTrue, semEqFlowCond(v, e, delta, isEq, testIsTrue0), testIsTrue0)
)
}
/**
* Holds if `v` is an `SsaExplicitUpdate` that equals `e + delta`.
*/
predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, int delta) {
exists(SemExpr defExpr | defExpr = v.getSourceExpr() |
defExpr.(SemCopyValueExpr).getOperand() = e and delta = 0
module RangeUtil<Range::DeltaSig D, Range::LangSig<D> Lang> implements Range::UtilSig<D> {
/**
* Gets an expression that equals `v - d`.
*/
SemExpr semSsaRead(SemSsaVariable v, D::Delta delta) {
// There are various language-specific extension points that can be removed once we no longer
// expect to match the original Java implementation's results exactly.
result = v.getAUse() and delta = D::fromInt(0)
or
defExpr.(SemStoreExpr).getOperand() = e and delta = 0
exists(D::Delta d1, SemConstantIntegerExpr c |
result.(SemAddExpr).hasOperands(semSsaRead(v, d1), c) and
delta = D::fromFloat(D::toFloat(d1) - c.getIntValue()) and
not Lang::ignoreSsaReadArithmeticExpr(result)
)
or
defExpr.(SemAddOneExpr).getOperand() = e and delta = 1
exists(SemSubExpr sub, D::Delta d1, SemConstantIntegerExpr c |
result = sub and
sub.getLeftOperand() = semSsaRead(v, d1) and
sub.getRightOperand() = c and
delta = D::fromFloat(D::toFloat(d1) + c.getIntValue()) and
not Lang::ignoreSsaReadArithmeticExpr(result)
)
or
defExpr.(SemSubOneExpr).getOperand() = e and delta = -1
result = v.(SemSsaExplicitUpdate).getSourceExpr() and
delta = D::fromFloat(0) and
not Lang::ignoreSsaReadAssignment(v)
or
e = defExpr and
not (
defExpr instanceof SemCopyValueExpr or
defExpr instanceof SemStoreExpr or
defExpr instanceof SemAddOneExpr or
defExpr instanceof SemSubOneExpr
) and
delta = 0
)
}
result = Lang::specificSsaRead(v, delta)
or
result.(SemCopyValueExpr).getOperand() = semSsaRead(v, delta) and
not Lang::ignoreSsaReadCopy(result)
or
result.(SemStoreExpr).getOperand() = semSsaRead(v, delta)
}
/**
* Holds if `e1 + delta` equals `e2`.
*/
predicate semValueFlowStep(SemExpr e2, SemExpr e1, int delta) {
e2.(SemCopyValueExpr).getOperand() = e1 and delta = 0
or
e2.(SemStoreExpr).getOperand() = e1 and delta = 0
or
e2.(SemAddOneExpr).getOperand() = e1 and delta = 1
or
e2.(SemSubOneExpr).getOperand() = e1 and delta = -1
or
Specific::additionalValueFlowStep(e2, e1, delta)
or
exists(SemExpr x | e2.(SemAddExpr).hasOperands(e1, x) |
x.(SemConstantIntegerExpr).getIntValue() = delta
)
or
exists(SemExpr x, SemSubExpr sub |
e2 = sub and
sub.getLeftOperand() = e1 and
sub.getRightOperand() = x
|
x.(SemConstantIntegerExpr).getIntValue() = -delta
)
}
/**
* Gets a condition that tests whether `v` equals `e + delta`.
*
* If the condition evaluates to `testIsTrue`:
* - `isEq = true` : `v == e + delta`
* - `isEq = false` : `v != e + delta`
*/
SemGuard semEqFlowCond(
SemSsaVariable v, SemExpr e, D::Delta delta, boolean isEq, boolean testIsTrue
) {
exists(boolean eqpolarity |
result.isEquality(semSsaRead(v, delta), e, eqpolarity) and
(testIsTrue = true or testIsTrue = false) and
eqpolarity.booleanXor(testIsTrue).booleanNot() = isEq
)
or
exists(boolean testIsTrue0 |
semImplies_v2(result, testIsTrue, semEqFlowCond(v, e, delta, isEq, testIsTrue0), testIsTrue0)
)
}
/**
* Gets the type used to track the specified expression's range information.
*
* Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed
* primitive types as the underlying primitive type.
*/
SemType getTrackedType(SemExpr e) {
result = Specific::getAlternateType(e)
or
not exists(Specific::getAlternateType(e)) and result = e.getSemType()
}
/**
* Holds if `v` is an `SsaExplicitUpdate` that equals `e + delta`.
*/
predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, D::Delta delta) {
exists(SemExpr defExpr | defExpr = v.getSourceExpr() |
defExpr.(SemCopyValueExpr).getOperand() = e and delta = D::fromFloat(0)
or
defExpr.(SemStoreExpr).getOperand() = e and delta = D::fromFloat(0)
or
defExpr.(SemAddOneExpr).getOperand() = e and delta = D::fromFloat(1)
or
defExpr.(SemSubOneExpr).getOperand() = e and delta = D::fromFloat(-1)
or
e = defExpr and
not (
defExpr instanceof SemCopyValueExpr or
defExpr instanceof SemStoreExpr or
defExpr instanceof SemAddOneExpr or
defExpr instanceof SemSubOneExpr
) and
delta = D::fromFloat(0)
)
}
/**
* Gets the type used to track the specified source variable's range information.
*
* Usually, this just `e.getType()`, but the language can override this to track immutable boxed
* primitive types as the underlying primitive type.
*/
SemType getTrackedTypeForSsaVariable(SemSsaVariable var) {
result = Specific::getAlternateTypeForSsaVariable(var)
or
not exists(Specific::getAlternateTypeForSsaVariable(var)) and result = var.getType()
/**
* Holds if `e1 + delta` equals `e2`.
*/
predicate semValueFlowStep(SemExpr e2, SemExpr e1, D::Delta delta) {
e2.(SemCopyValueExpr).getOperand() = e1 and delta = D::fromFloat(0)
or
e2.(SemStoreExpr).getOperand() = e1 and delta = D::fromFloat(0)
or
e2.(SemAddOneExpr).getOperand() = e1 and delta = D::fromFloat(1)
or
e2.(SemSubOneExpr).getOperand() = e1 and delta = D::fromFloat(-1)
or
Lang::additionalValueFlowStep(e2, e1, delta)
or
exists(SemExpr x | e2.(SemAddExpr).hasOperands(e1, x) |
D::fromInt(x.(SemConstantIntegerExpr).getIntValue()) = delta
)
or
exists(SemExpr x, SemSubExpr sub |
e2 = sub and
sub.getLeftOperand() = e1 and
sub.getRightOperand() = x
|
D::fromInt(-x.(SemConstantIntegerExpr).getIntValue()) = delta
)
}
/**
* Gets the type used to track the specified expression's range information.
*
* Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed
* primitive types as the underlying primitive type.
*/
SemType getTrackedType(SemExpr e) {
result = Lang::getAlternateType(e)
or
not exists(Lang::getAlternateType(e)) and result = e.getSemType()
}
/**
* Gets the type used to track the specified source variable's range information.
*
* Usually, this just `e.getType()`, but the language can override this to track immutable boxed
* primitive types as the underlying primitive type.
*/
SemType getTrackedTypeForSsaVariable(SemSsaVariable var) {
result = Lang::getAlternateTypeForSsaVariable(var)
or
not exists(Lang::getAlternateTypeForSsaVariable(var)) and result = var.getType()
}
}

View File

@@ -6,488 +6,494 @@
* three-valued domain `{negative, zero, positive}`.
*/
private import RangeAnalysisStage
private import SignAnalysisSpecific as Specific
private import experimental.semmle.code.cpp.semantic.Semantic
private import ConstantAnalysis
private import RangeUtils
private import Sign
/**
* An SSA definition for which the analysis can compute the sign.
*
* The actual computation of the sign is done in an override of the `getSign()` predicate. The
* charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures
* that the charpred does not introduce negative recursion. The `getSign()` predicate may be
* recursive.
*/
abstract private class SignDef instanceof SemSsaVariable {
final string toString() { result = super.toString() }
module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
/**
* An SSA definition for which the analysis can compute the sign.
*
* The actual computation of the sign is done in an override of the `getSign()` predicate. The
* charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures
* that the charpred does not introduce negative recursion. The `getSign()` predicate may be
* recursive.
*/
abstract private class SignDef instanceof SemSsaVariable {
final string toString() { result = super.toString() }
/** Gets the possible signs of this SSA definition. */
abstract Sign getSign();
}
/** An SSA definition whose sign is computed based on standard flow. */
abstract private class FlowSignDef extends SignDef {
abstract override Sign getSign();
}
/** An SSA definition whose sign is determined by the sign of that definitions source expression. */
private class ExplicitSignDef extends FlowSignDef instanceof SemSsaExplicitUpdate {
final override Sign getSign() { result = semExprSign(super.getSourceExpr()) }
}
/** An SSA Phi definition, whose sign is the union of the signs of its inputs. */
private class PhiSignDef extends FlowSignDef instanceof SemSsaPhiNode {
final override Sign getSign() {
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
edge.phiInput(this, inp) and
result = semSsaSign(inp, edge)
)
}
}
/** An SSA definition whose sign is computed by a language-specific implementation. */
abstract class CustomSignDef extends SignDef {
abstract override Sign getSign();
}
/**
* An expression for which the analysis can compute the sign.
*
* The actual computation of the sign is done in an override of the `getSign()` predicate. The
* charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures
* that the charpred does not introduce negative recursion. The `getSign()` predicate may be
* recursive.
*
* Concrete implementations extend one of the following subclasses:
* - `ConstantSignExpr`, for expressions with a compile-time constant value.
* - `FlowSignExpr`, for expressions whose sign can be computed from the signs of their operands.
* - `CustomsignExpr`, for expressions whose sign can be computed by a language-specific
* implementation.
*
* If the same expression matches more than one of the above subclasses, the sign is computed as
* follows:
* - The sign of a `ConstantSignExpr` is computed solely from `ConstantSignExpr.getSign()`,
* regardless of any other subclasses.
* - If a non-`ConstantSignExpr` expression matches exactly one of `FlowSignExpr` or
* `CustomSignExpr`, the sign is computed by that class' `getSign()` predicate.
* - If a non-`ConstantSignExpr` expression matches both `FlowSignExpr` and `CustomSignExpr`, the
* sign is the _intersection_ of the signs of those two classes' `getSign()` predicates. Thus,
* both classes have the opportunity to _restrict_ the set of possible signs, not to generate new
* possible signs.
* - If an expression does not match any of the three subclasses, then it can have any sign.
*
* Note that the `getSign()` predicate is introduced only in subclasses of `SignExpr`.
*/
abstract class SignExpr instanceof SemExpr {
SignExpr() { not Specific::ignoreExprSign(this) }
final string toString() { result = super.toString() }
abstract Sign getSign();
}
/** An expression whose sign is determined by its constant numeric value. */
private class ConstantSignExpr extends SignExpr {
ConstantSignExpr() {
this instanceof SemConstantIntegerExpr or
exists(this.(SemNumericLiteralExpr).getApproximateFloatValue())
/** Gets the possible signs of this SSA definition. */
abstract Sign getSign();
}
final override Sign getSign() {
exists(int i | this.(SemConstantIntegerExpr).getIntValue() = i |
i < 0 and result = TNeg()
/** An SSA definition whose sign is computed based on standard flow. */
abstract private class FlowSignDef extends SignDef {
abstract override Sign getSign();
}
/** An SSA definition whose sign is determined by the sign of that definitions source expression. */
private class ExplicitSignDef extends FlowSignDef instanceof SemSsaExplicitUpdate {
final override Sign getSign() { result = semExprSign(super.getSourceExpr()) }
}
/** An SSA Phi definition, whose sign is the union of the signs of its inputs. */
private class PhiSignDef extends FlowSignDef instanceof SemSsaPhiNode {
final override Sign getSign() {
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
edge.phiInput(this, inp) and
result = semSsaSign(inp, edge)
)
}
}
/** An SSA definition whose sign is computed by a language-specific implementation. */
abstract class CustomSignDef extends SignDef {
abstract override Sign getSign();
}
/**
* An expression for which the analysis can compute the sign.
*
* The actual computation of the sign is done in an override of the `getSign()` predicate. The
* charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures
* that the charpred does not introduce negative recursion. The `getSign()` predicate may be
* recursive.
*
* Concrete implementations extend one of the following subclasses:
* - `ConstantSignExpr`, for expressions with a compile-time constant value.
* - `FlowSignExpr`, for expressions whose sign can be computed from the signs of their operands.
* - `CustomsignExpr`, for expressions whose sign can be computed by a language-specific
* implementation.
*
* If the same expression matches more than one of the above subclasses, the sign is computed as
* follows:
* - The sign of a `ConstantSignExpr` is computed solely from `ConstantSignExpr.getSign()`,
* regardless of any other subclasses.
* - If a non-`ConstantSignExpr` expression matches exactly one of `FlowSignExpr` or
* `CustomSignExpr`, the sign is computed by that class' `getSign()` predicate.
* - If a non-`ConstantSignExpr` expression matches both `FlowSignExpr` and `CustomSignExpr`, the
* sign is the _intersection_ of the signs of those two classes' `getSign()` predicates. Thus,
* both classes have the opportunity to _restrict_ the set of possible signs, not to generate new
* possible signs.
* - If an expression does not match any of the three subclasses, then it can have any sign.
*
* Note that the `getSign()` predicate is introduced only in subclasses of `SignExpr`.
*/
abstract class SignExpr instanceof SemExpr {
SignExpr() { not Specific::ignoreExprSign(this) }
final string toString() { result = super.toString() }
abstract Sign getSign();
}
/** An expression whose sign is determined by its constant numeric value. */
private class ConstantSignExpr extends SignExpr {
ConstantSignExpr() {
this instanceof SemConstantIntegerExpr or
exists(this.(SemNumericLiteralExpr).getApproximateFloatValue())
}
final override Sign getSign() {
exists(int i | this.(SemConstantIntegerExpr).getIntValue() = i |
i < 0 and result = TNeg()
or
i = 0 and result = TZero()
or
i > 0 and result = TPos()
)
or
i = 0 and result = TZero()
or
i > 0 and result = TPos()
)
or
not exists(this.(SemConstantIntegerExpr).getIntValue()) and
exists(float f | f = this.(SemNumericLiteralExpr).getApproximateFloatValue() |
f < 0 and result = TNeg()
or
f = 0 and result = TZero()
or
f > 0 and result = TPos()
)
}
}
abstract private class NonConstantSignExpr extends SignExpr {
NonConstantSignExpr() { not this instanceof ConstantSignExpr }
final override Sign getSign() {
// The result is the _intersection_ of the signs computed from flow and by the language.
(result = this.(FlowSignExpr).getSignRestriction() or not this instanceof FlowSignExpr) and
(result = this.(CustomSignExpr).getSignRestriction() or not this instanceof CustomSignExpr)
}
}
/** An expression whose sign is computed from the signs of its operands. */
abstract private class FlowSignExpr extends NonConstantSignExpr {
abstract Sign getSignRestriction();
}
/** An expression whose sign is computed by a language-specific implementation. */
abstract class CustomSignExpr extends NonConstantSignExpr {
abstract Sign getSignRestriction();
}
/** An expression whose sign is unknown. */
private class UnknownSignExpr extends SignExpr {
UnknownSignExpr() {
not this instanceof FlowSignExpr and
not this instanceof CustomSignExpr and
not this instanceof ConstantSignExpr and
(
// Only track numeric types.
getTrackedType(this) instanceof SemNumericType
or
// Unless the language says to track this expression anyway.
Specific::trackUnknownNonNumericExpr(this)
)
not exists(this.(SemConstantIntegerExpr).getIntValue()) and
exists(float f | f = this.(SemNumericLiteralExpr).getApproximateFloatValue() |
f < 0 and result = TNeg()
or
f = 0 and result = TZero()
or
f > 0 and result = TPos()
)
}
}
final override Sign getSign() { semAnySign(result) }
}
abstract private class NonConstantSignExpr extends SignExpr {
NonConstantSignExpr() { not this instanceof ConstantSignExpr }
/**
* A `Load` expression whose sign is computed from the sign of its SSA definition, restricted by
* inference from any intervening guards.
*/
class UseSignExpr extends FlowSignExpr {
SemSsaVariable v;
UseSignExpr() { v.getAUse() = this }
override Sign getSignRestriction() {
// Propagate via SSA
// Propagate the sign from the def of `v`, incorporating any inference from guards.
result = semSsaSign(v, any(SemSsaReadPositionBlock bb | bb.getAnExpr() = this))
or
// No block for this read. Just use the sign of the def.
// REVIEW: How can this happen?
not exists(SemSsaReadPositionBlock bb | bb.getAnExpr() = this) and
result = semSsaDefSign(v)
final override Sign getSign() {
// The result is the _intersection_ of the signs computed from flow and by the language.
(result = this.(FlowSignExpr).getSignRestriction() or not this instanceof FlowSignExpr) and
(result = this.(CustomSignExpr).getSignRestriction() or not this instanceof CustomSignExpr)
}
}
}
/** A binary expression whose sign is computed from the signs of its operands. */
private class BinarySignExpr extends FlowSignExpr {
SemBinaryExpr binary;
/** An expression whose sign is computed from the signs of its operands. */
abstract private class FlowSignExpr extends NonConstantSignExpr {
abstract Sign getSignRestriction();
}
BinarySignExpr() { binary = this }
/** An expression whose sign is computed by a language-specific implementation. */
abstract class CustomSignExpr extends NonConstantSignExpr {
abstract Sign getSignRestriction();
}
override Sign getSignRestriction() {
exists(SemExpr left, SemExpr right |
binaryExprOperands(binary, left, right) and
/** An expression whose sign is unknown. */
private class UnknownSignExpr extends SignExpr {
UnknownSignExpr() {
not this instanceof FlowSignExpr and
not this instanceof CustomSignExpr and
not this instanceof ConstantSignExpr and
(
// Only track numeric types.
Utils::getTrackedType(this) instanceof SemNumericType
or
// Unless the language says to track this expression anyway.
Specific::trackUnknownNonNumericExpr(this)
)
}
final override Sign getSign() { semAnySign(result) }
}
/**
* A `Load` expression whose sign is computed from the sign of its SSA definition, restricted by
* inference from any intervening guards.
*/
class UseSignExpr extends FlowSignExpr {
SemSsaVariable v;
UseSignExpr() { v.getAUse() = this }
override Sign getSignRestriction() {
// Propagate via SSA
// Propagate the sign from the def of `v`, incorporating any inference from guards.
result = semSsaSign(v, any(SemSsaReadPositionBlock bb | bb.getAnExpr() = this))
or
// No block for this read. Just use the sign of the def.
// REVIEW: How can this happen?
not exists(SemSsaReadPositionBlock bb | bb.getAnExpr() = this) and
result = semSsaDefSign(v)
}
}
/** A binary expression whose sign is computed from the signs of its operands. */
private class BinarySignExpr extends FlowSignExpr {
SemBinaryExpr binary;
BinarySignExpr() { binary = this }
override Sign getSignRestriction() {
exists(SemExpr left, SemExpr right |
binaryExprOperands(binary, left, right) and
result =
semExprSign(pragma[only_bind_out](left))
.applyBinaryOp(semExprSign(pragma[only_bind_out](right)), binary.getOpcode())
)
or
exists(SemDivExpr div | div = binary |
result = semExprSign(div.getLeftOperand()) and
result != TZero() and
div.getRightOperand().(SemFloatingPointLiteralExpr).getFloatValue() = 0
)
}
}
pragma[nomagic]
private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) {
binary.getLeftOperand() = left and binary.getRightOperand() = right
}
/**
* A `Convert`, `Box`, or `Unbox` expression.
*/
private class SemCastExpr instanceof SemUnaryExpr {
string toString() { result = super.toString() }
SemCastExpr() {
this instanceof SemConvertExpr
or
this instanceof SemBoxExpr
or
this instanceof SemUnboxExpr
}
}
/** A unary expression whose sign is computed from the sign of its operand. */
private class UnarySignExpr extends FlowSignExpr {
SemUnaryExpr unary;
UnarySignExpr() { unary = this and not this instanceof SemCastExpr }
override Sign getSignRestriction() {
result =
semExprSign(pragma[only_bind_out](left))
.applyBinaryOp(semExprSign(pragma[only_bind_out](right)), binary.getOpcode())
)
or
exists(SemDivExpr div | div = binary |
result = semExprSign(div.getLeftOperand()) and
result != TZero() and
div.getRightOperand().(SemFloatingPointLiteralExpr).getFloatValue() = 0
semExprSign(pragma[only_bind_out](unary.getOperand())).applyUnaryOp(unary.getOpcode())
}
}
/**
* A `Convert`, `Box`, or `Unbox` expression, whose sign is computed based on
* the sign of its operand and the source and destination types.
*/
abstract private class CastSignExpr extends FlowSignExpr {
SemUnaryExpr cast;
CastSignExpr() { cast = this and cast instanceof SemCastExpr }
override Sign getSignRestriction() { result = semExprSign(cast.getOperand()) }
}
/**
* A `Convert` expression.
*/
private class ConvertSignExpr extends CastSignExpr {
override SemConvertExpr cast;
}
/**
* A `Box` expression.
*/
private class BoxSignExpr extends CastSignExpr {
override SemBoxExpr cast;
}
/**
* An `Unbox` expression.
*/
private class UnboxSignExpr extends CastSignExpr {
override SemUnboxExpr cast;
UnboxSignExpr() {
exists(SemType fromType | fromType = Utils::getTrackedType(cast.getOperand()) |
// Only numeric source types are handled here.
fromType instanceof SemNumericType
)
}
}
private predicate unknownSign(SemExpr e) { e instanceof UnknownSignExpr }
/**
* Holds if `lowerbound` is a lower bound for `v` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
private predicate lowerBound(
SemExpr lowerbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict
) {
exists(boolean testIsTrue, SemRelationalExpr comp |
pos.hasReadOfVar(v) and
semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
not unknownSign(lowerbound)
|
testIsTrue = true and
comp.getLesserOperand() = lowerbound and
comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
(if comp.isStrict() then isStrict = true else isStrict = false)
or
testIsTrue = false and
comp.getGreaterOperand() = lowerbound and
comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
(if comp.isStrict() then isStrict = false else isStrict = true)
)
}
}
pragma[nomagic]
private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) {
binary.getLeftOperand() = left and binary.getRightOperand() = right
}
/**
* A `Convert`, `Box`, or `Unbox` expression.
*/
private class SemCastExpr extends SemUnaryExpr {
SemCastExpr() {
this instanceof SemConvertExpr
or
this instanceof SemBoxExpr
or
this instanceof SemUnboxExpr
}
}
/** A unary expression whose sign is computed from the sign of its operand. */
private class UnarySignExpr extends FlowSignExpr {
SemUnaryExpr unary;
UnarySignExpr() { unary = this and not this instanceof SemCastExpr }
override Sign getSignRestriction() {
result = semExprSign(pragma[only_bind_out](unary.getOperand())).applyUnaryOp(unary.getOpcode())
}
}
/**
* A `Convert`, `Box`, or `Unbox` expression, whose sign is computed based on
* the sign of its operand and the source and destination types.
*/
abstract private class CastSignExpr extends FlowSignExpr {
SemUnaryExpr cast;
CastSignExpr() { cast = this and cast instanceof SemCastExpr }
override Sign getSignRestriction() { result = semExprSign(cast.getOperand()) }
}
/**
* A `Convert` expression.
*/
private class ConvertSignExpr extends CastSignExpr {
override SemConvertExpr cast;
}
/**
* A `Box` expression.
*/
private class BoxSignExpr extends CastSignExpr {
override SemBoxExpr cast;
}
/**
* An `Unbox` expression.
*/
private class UnboxSignExpr extends CastSignExpr {
override SemUnboxExpr cast;
UnboxSignExpr() {
exists(SemType fromType | fromType = getTrackedType(cast.getOperand()) |
// Only numeric source types are handled here.
fromType instanceof SemNumericType
/**
* Holds if `upperbound` is an upper bound for `v` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
private predicate upperBound(
SemExpr upperbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict
) {
exists(boolean testIsTrue, SemRelationalExpr comp |
pos.hasReadOfVar(v) and
semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
not unknownSign(upperbound)
|
testIsTrue = true and
comp.getGreaterOperand() = upperbound and
comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
(if comp.isStrict() then isStrict = true else isStrict = false)
or
testIsTrue = false and
comp.getLesserOperand() = upperbound and
comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
(if comp.isStrict() then isStrict = false else isStrict = true)
)
}
}
private predicate unknownSign(SemExpr e) { e instanceof UnknownSignExpr }
/**
* Holds if `eqbound` is an equality/inequality for `v` at `pos`. This is
* restricted to only include bounds for which we might determine a sign. The
* boolean `isEq` gives the polarity:
* - `isEq = true` : `v = eqbound`
* - `isEq = false` : `v != eqbound`
*/
private predicate eqBound(SemExpr eqbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isEq) {
exists(SemGuard guard, boolean testIsTrue, boolean polarity |
pos.hasReadOfVar(v) and
semGuardControlsSsaRead(guard, pos, testIsTrue) and
guard.isEquality(eqbound, Utils::semSsaRead(v, D::fromInt(0)), polarity) and
isEq = polarity.booleanXor(testIsTrue).booleanNot() and
not unknownSign(eqbound)
)
}
/**
* Holds if `lowerbound` is a lower bound for `v` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
private predicate lowerBound(
SemExpr lowerbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict
) {
exists(boolean testIsTrue, SemRelationalExpr comp |
pos.hasReadOfVar(v) and
semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
not unknownSign(lowerbound)
|
testIsTrue = true and
comp.getLesserOperand() = lowerbound and
comp.getGreaterOperand() = semSsaRead(v, 0) and
(if comp.isStrict() then isStrict = true else isStrict = false)
/**
* Holds if `bound` is a bound for `v` at `pos` that needs to be positive in
* order for `v` to be positive.
*/
private predicate posBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
upperBound(bound, v, pos, _) or
eqBound(bound, v, pos, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that needs to be negative in
* order for `v` to be negative.
*/
private predicate negBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
lowerBound(bound, v, pos, _) or
eqBound(bound, v, pos, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v`
* can be zero.
*/
private predicate zeroBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
lowerBound(bound, v, pos, _) or
upperBound(bound, v, pos, _) or
eqBound(bound, v, pos, _)
}
/** Holds if `bound` allows `v` to be positive at `pos`. */
private predicate posBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
posBound(bound, v, pos) and TPos() = semExprSign(bound)
}
/** Holds if `bound` allows `v` to be negative at `pos`. */
private predicate negBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
negBound(bound, v, pos) and TNeg() = semExprSign(bound)
}
/** Holds if `bound` allows `v` to be zero at `pos`. */
private predicate zeroBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
lowerBound(bound, v, pos, _) and TNeg() = semExprSign(bound)
or
testIsTrue = false and
comp.getGreaterOperand() = lowerbound and
comp.getLesserOperand() = semSsaRead(v, 0) and
(if comp.isStrict() then isStrict = false else isStrict = true)
)
}
/**
* Holds if `upperbound` is an upper bound for `v` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
private predicate upperBound(
SemExpr upperbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict
) {
exists(boolean testIsTrue, SemRelationalExpr comp |
pos.hasReadOfVar(v) and
semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
not unknownSign(upperbound)
|
testIsTrue = true and
comp.getGreaterOperand() = upperbound and
comp.getLesserOperand() = semSsaRead(v, 0) and
(if comp.isStrict() then isStrict = true else isStrict = false)
lowerBound(bound, v, pos, false) and TZero() = semExprSign(bound)
or
testIsTrue = false and
comp.getLesserOperand() = upperbound and
comp.getGreaterOperand() = semSsaRead(v, 0) and
(if comp.isStrict() then isStrict = false else isStrict = true)
)
}
upperBound(bound, v, pos, _) and TPos() = semExprSign(bound)
or
upperBound(bound, v, pos, false) and TZero() = semExprSign(bound)
or
eqBound(bound, v, pos, true) and TZero() = semExprSign(bound)
or
eqBound(bound, v, pos, false) and TZero() != semExprSign(bound)
}
/**
* Holds if `eqbound` is an equality/inequality for `v` at `pos`. This is
* restricted to only include bounds for which we might determine a sign. The
* boolean `isEq` gives the polarity:
* - `isEq = true` : `v = eqbound`
* - `isEq = false` : `v != eqbound`
*/
private predicate eqBound(SemExpr eqbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isEq) {
exists(SemGuard guard, boolean testIsTrue, boolean polarity |
/**
* Holds if there is a bound that might restrict whether `v` has the sign `s`
* at `pos`.
*/
private predicate hasGuard(SemSsaVariable v, SemSsaReadPosition pos, Sign s) {
s = TPos() and posBound(_, v, pos)
or
s = TNeg() and negBound(_, v, pos)
or
s = TZero() and zeroBound(_, v, pos)
}
/**
* Gets a possible sign of `v` at `pos` based on its definition, where the sign
* might be ruled out by a guard.
*/
pragma[noinline]
private Sign guardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) {
result = semSsaDefSign(v) and
pos.hasReadOfVar(v) and
semGuardControlsSsaRead(guard, pos, testIsTrue) and
guard.isEquality(eqbound, semSsaRead(v, 0), polarity) and
isEq = polarity.booleanXor(testIsTrue).booleanNot() and
not unknownSign(eqbound)
)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that needs to be positive in
* order for `v` to be positive.
*/
private predicate posBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
upperBound(bound, v, pos, _) or
eqBound(bound, v, pos, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that needs to be negative in
* order for `v` to be negative.
*/
private predicate negBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
lowerBound(bound, v, pos, _) or
eqBound(bound, v, pos, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v`
* can be zero.
*/
private predicate zeroBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
lowerBound(bound, v, pos, _) or
upperBound(bound, v, pos, _) or
eqBound(bound, v, pos, _)
}
/** Holds if `bound` allows `v` to be positive at `pos`. */
private predicate posBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
posBound(bound, v, pos) and TPos() = semExprSign(bound)
}
/** Holds if `bound` allows `v` to be negative at `pos`. */
private predicate negBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
negBound(bound, v, pos) and TNeg() = semExprSign(bound)
}
/** Holds if `bound` allows `v` to be zero at `pos`. */
private predicate zeroBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) {
lowerBound(bound, v, pos, _) and TNeg() = semExprSign(bound)
or
lowerBound(bound, v, pos, false) and TZero() = semExprSign(bound)
or
upperBound(bound, v, pos, _) and TPos() = semExprSign(bound)
or
upperBound(bound, v, pos, false) and TZero() = semExprSign(bound)
or
eqBound(bound, v, pos, true) and TZero() = semExprSign(bound)
or
eqBound(bound, v, pos, false) and TZero() != semExprSign(bound)
}
/**
* Holds if there is a bound that might restrict whether `v` has the sign `s`
* at `pos`.
*/
private predicate hasGuard(SemSsaVariable v, SemSsaReadPosition pos, Sign s) {
s = TPos() and posBound(_, v, pos)
or
s = TNeg() and negBound(_, v, pos)
or
s = TZero() and zeroBound(_, v, pos)
}
/**
* Gets a possible sign of `v` at `pos` based on its definition, where the sign
* might be ruled out by a guard.
*/
pragma[noinline]
private Sign guardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) {
result = semSsaDefSign(v) and
pos.hasReadOfVar(v) and
hasGuard(v, pos, result)
}
/**
* Gets a possible sign of `v` at `pos` based on its definition, where no guard
* can rule it out.
*/
pragma[noinline]
private Sign unguardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) {
result = semSsaDefSign(v) and
pos.hasReadOfVar(v) and
not hasGuard(v, pos, result)
}
/**
* Gets a possible sign of `v` at read position `pos`, where a guard could have
* ruled out the sign but does not.
* This does not check that the definition of `v` also allows the sign.
*/
private Sign guardedSsaSignOk(SemSsaVariable v, SemSsaReadPosition pos) {
result = TPos() and
forex(SemExpr bound | posBound(bound, v, pos) | posBoundOk(bound, v, pos))
or
result = TNeg() and
forex(SemExpr bound | negBound(bound, v, pos) | negBoundOk(bound, v, pos))
or
result = TZero() and
forex(SemExpr bound | zeroBound(bound, v, pos) | zeroBoundOk(bound, v, pos))
}
/** Gets a possible sign for `v` at `pos`. */
private Sign semSsaSign(SemSsaVariable v, SemSsaReadPosition pos) {
result = unguardedSsaSign(v, pos)
or
result = guardedSsaSign(v, pos) and
result = guardedSsaSignOk(v, pos)
}
/** Gets a possible sign for `v`. */
pragma[nomagic]
Sign semSsaDefSign(SemSsaVariable v) { result = v.(SignDef).getSign() }
/** Gets a possible sign for `e`. */
cached
Sign semExprSign(SemExpr e) {
exists(Sign s | s = e.(SignExpr).getSign() |
if
getTrackedType(e) instanceof SemUnsignedIntegerType and
s = TNeg() and
not Specific::ignoreTypeRestrictions(e)
then result = TPos()
else result = s
)
}
/**
* Dummy predicate that holds for any sign. This is added to improve readability
* of cases where the sign is unrestricted.
*/
predicate semAnySign(Sign s) { any() }
/** Holds if `e` can be positive and cannot be negative. */
predicate semPositive(SemExpr e) {
semExprSign(e) = TPos() and
not semExprSign(e) = TNeg()
}
/** Holds if `e` can be negative and cannot be positive. */
predicate semNegative(SemExpr e) {
semExprSign(e) = TNeg() and
not semExprSign(e) = TPos()
}
/** Holds if `e` is strictly positive. */
predicate semStrictlyPositive(SemExpr e) {
semExprSign(e) = TPos() and
not semExprSign(e) = TNeg() and
not semExprSign(e) = TZero()
}
/** Holds if `e` is strictly negative. */
predicate semStrictlyNegative(SemExpr e) {
semExprSign(e) = TNeg() and
not semExprSign(e) = TPos() and
not semExprSign(e) = TZero()
hasGuard(v, pos, result)
}
/**
* Gets a possible sign of `v` at `pos` based on its definition, where no guard
* can rule it out.
*/
pragma[noinline]
private Sign unguardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) {
result = semSsaDefSign(v) and
pos.hasReadOfVar(v) and
not hasGuard(v, pos, result)
}
/**
* Gets a possible sign of `v` at read position `pos`, where a guard could have
* ruled out the sign but does not.
* This does not check that the definition of `v` also allows the sign.
*/
private Sign guardedSsaSignOk(SemSsaVariable v, SemSsaReadPosition pos) {
result = TPos() and
forex(SemExpr bound | posBound(bound, v, pos) | posBoundOk(bound, v, pos))
or
result = TNeg() and
forex(SemExpr bound | negBound(bound, v, pos) | negBoundOk(bound, v, pos))
or
result = TZero() and
forex(SemExpr bound | zeroBound(bound, v, pos) | zeroBoundOk(bound, v, pos))
}
/** Gets a possible sign for `v` at `pos`. */
private Sign semSsaSign(SemSsaVariable v, SemSsaReadPosition pos) {
result = unguardedSsaSign(v, pos)
or
result = guardedSsaSign(v, pos) and
result = guardedSsaSignOk(v, pos)
}
/** Gets a possible sign for `v`. */
pragma[nomagic]
Sign semSsaDefSign(SemSsaVariable v) { result = v.(SignDef).getSign() }
/** Gets a possible sign for `e`. */
cached
Sign semExprSign(SemExpr e) {
exists(Sign s | s = e.(SignExpr).getSign() |
if
Utils::getTrackedType(e) instanceof SemUnsignedIntegerType and
s = TNeg() and
not Specific::ignoreTypeRestrictions(e)
then result = TPos()
else result = s
)
}
/**
* Dummy predicate that holds for any sign. This is added to improve readability
* of cases where the sign is unrestricted.
*/
predicate semAnySign(Sign s) { any() }
/** Holds if `e` can be positive and cannot be negative. */
predicate semPositive(SemExpr e) {
semExprSign(e) = TPos() and
not semExprSign(e) = TNeg()
}
/** Holds if `e` can be negative and cannot be positive. */
predicate semNegative(SemExpr e) {
semExprSign(e) = TNeg() and
not semExprSign(e) = TPos()
}
/** Holds if `e` is strictly positive. */
predicate semStrictlyPositive(SemExpr e) {
semExprSign(e) = TPos() and
not semExprSign(e) = TNeg() and
not semExprSign(e) = TZero()
}
/** Holds if `e` is strictly negative. */
predicate semStrictlyNegative(SemExpr e) {
semExprSign(e) = TNeg() and
not semExprSign(e) = TPos() and
not semExprSign(e) = TZero()
}
}

View File

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

View File

@@ -318,7 +318,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
MetricFunction getMetrics() { result = this }
/** Holds if this function calls the function `f`. */
predicate calls(Function f) { exists(Locatable l | this.calls(f, l)) }
predicate calls(Function f) { this.calls(f, _) }
/**
* Holds if this function calls the function `f` in the `FunctionCall`
@@ -335,7 +335,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
}
/** Holds if this function accesses a function or variable or enumerator `a`. */
predicate accesses(Declaration a) { exists(Locatable l | this.accesses(a, l)) }
predicate accesses(Declaration a) { this.accesses(a, _) }
/**
* Holds if this function accesses a function or variable or enumerator `a`

View File

@@ -10,12 +10,14 @@ import semmle.code.cpp.File
*/
class Location extends @location {
/** Gets the container corresponding to this location. */
pragma[nomagic]
Container getContainer() { this.fullLocationInfo(result, _, _, _, _) }
/** Gets the file corresponding to this location, if any. */
File getFile() { result = this.getContainer() }
/** Gets the 1-based line number (inclusive) where this location starts. */
pragma[nomagic]
int getStartLine() { this.fullLocationInfo(_, result, _, _, _) }
/** Gets the 1-based column number (inclusive) where this location starts. */

View File

@@ -816,6 +816,12 @@ private predicate floatingPointTypeMapping(
or
// _Float128x
kind = 50 and base = 2 and domain = TRealDomain() and realKind = 50 and extended = true
or
// _Float16
kind = 52 and base = 2 and domain = TRealDomain() and realKind = 52 and extended = false
or
// _Complex _Float16
kind = 53 and base = 2 and domain = TComplexDomain() and realKind = 52 and extended = false
}
/**

View File

@@ -33,7 +33,7 @@ DependencyOptions getDependencyOptions() { any() }
class DependsSource extends Element {
DependsSource() {
// not inside a template instantiation
not exists(Element other | this.isFromTemplateInstantiation(other)) or
not this.isFromTemplateInstantiation(_) or
// allow DeclarationEntrys of template specializations
this.(DeclarationEntry).getDeclaration().(Function).isConstructedFrom(_) or
this.(DeclarationEntry).getDeclaration().(Class).isConstructedFrom(_)

View File

@@ -69,12 +69,9 @@ predicate functionContainsDisabledCode(Function f) {
*/
predicate functionContainsPreprocCode(Function f) {
// `f` contains a preprocessor branch
exists(
PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine,
int fBlockEndLine
|
exists(string file, int pbdStartLine, int fBlockStartLine, int fBlockEndLine |
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
pbdLocation(pbd, file, pbdStartLine) and
pbdLocation(_, file, pbdStartLine) and
pbdStartLine <= fBlockEndLine and
pbdStartLine >= fBlockStartLine
)

View File

@@ -244,9 +244,7 @@ class ScanfFormatLiteral extends Expr {
/**
* Gets the maximum width option of the nth input (empty string if none is given).
*/
string getMaxWidthOpt(int n) {
exists(string spec, string len, string conv | this.parseConvSpec(n, spec, result, len, conv))
}
string getMaxWidthOpt(int n) { this.parseConvSpec(n, _, result, _, _) }
/**
* Gets the maximum width of the nth input.
@@ -256,18 +254,12 @@ class ScanfFormatLiteral extends Expr {
/**
* Gets the length flag of the nth conversion specifier.
*/
string getLength(int n) {
exists(string spec, string width, string conv |
this.parseConvSpec(n, spec, width, result, conv)
)
}
string getLength(int n) { this.parseConvSpec(n, _, _, result, _) }
/**
* Gets the conversion character of the nth conversion specifier.
*/
string getConversionChar(int n) {
exists(string spec, string width, string len | this.parseConvSpec(n, spec, width, len, result))
}
string getConversionChar(int n) { this.parseConvSpec(n, _, _, _, result) }
/**
* Gets the maximum length of the string that can be produced by the nth

View File

@@ -54,7 +54,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
* only condition under which a `SubBasicBlock` may have multiple
* predecessors.
*/
predicate firstInBB() { exists(BasicBlock bb | this.getRankInBasicBlock(bb) = 1) }
predicate firstInBB() { this.getRankInBasicBlock(_) = 1 }
/**
* Holds if this `SubBasicBlock` comes last in its basic block. This is the

View File

@@ -441,8 +441,8 @@ library class ExprEvaluator extends int {
req = mid.(AssignExpr).getRValue()
)
or
exists(VariableAccess va, Variable v, boolean sub1 |
this.interestingVariableAccess(e, va, v, sub1) and
exists(Variable v, boolean sub1 |
this.interestingVariableAccess(e, _, v, sub1) and
req = v.getAnAssignedValue() and
(sub1 = true implies not this.ignoreVariableAssignment(e, v, req)) and
sub = false
@@ -876,7 +876,7 @@ private predicate nonAnalyzableVariableDefinition(Variable v, StmtParent def) {
* empirically to have effect only on a few rare and pathological examples.
*/
private predicate tractableVariable(Variable v) {
not exists(StmtParent def | nonAnalyzableVariableDefinition(v, def)) or
not nonAnalyzableVariableDefinition(v, _) or
strictcount(StmtParent def | nonAnalyzableVariableDefinition(v, def)) < 1000
}

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or
@@ -1391,6 +1391,9 @@ class TypedContentApprox extends MkTypedContentApprox {
/** Gets a typed content approximated by this value. */
TypedContent getATypedContent() { result = getATypedContent(this) }
/** Gets the content. */
ContentApprox getContent() { result = c }
/** Gets the container type. */
DataFlowType getContainerType() { result = t }
@@ -1408,6 +1411,8 @@ abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
abstract boolean toBoolNonEmpty();
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
pragma[nomagic]
TypedContent getAHead() {
exists(TypedContentApprox cont |

View File

@@ -45,6 +45,16 @@ module Consistency {
) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodeAtPosition`. */
predicate uniqueParameterNodeAtPositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodePosition`. */
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
}
private class RelevantNode extends Node {
@@ -101,9 +111,7 @@ module Consistency {
exists(int c |
c =
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not n.hasLocationInfo(_, _, _, _, _) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
) and
msg = "Nodes without location: " + c
@@ -248,6 +256,7 @@ module Consistency {
query predicate uniqueParameterNodeAtPosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodeAtPositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(Node p0 | isParameterNode(p0, c, pos))) and
msg = "Parameters with overlapping positions."
@@ -256,6 +265,7 @@ module Consistency {
query predicate uniqueParameterNodePosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodePositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and
msg = "Parameter node with multiple positions."

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -450,10 +450,8 @@ module FlowVar_internal {
}
override string toString() {
exists(Expr e |
this.definedByExpr(e, _) and
result = "assignment to " + v
)
this.definedByExpr(_, _) and
result = "assignment to " + v
or
this.definedByInitialValue(_) and
result = "initial value of " + v

View File

@@ -54,7 +54,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
* only condition under which a `SubBasicBlock` may have multiple
* predecessors.
*/
predicate firstInBB() { exists(BasicBlock bb | this.getRankInBasicBlock(bb) = 1) }
predicate firstInBB() { this.getRankInBasicBlock(_) = 1 }
/**
* Holds if this `SubBasicBlock` comes last in its basic block. This is the

View File

@@ -70,8 +70,8 @@ module VirtualDispatch {
* that is, `c` or one of its supertypes overrides `f`.
*/
private predicate cannotInherit(Class c, MemberFunction f) {
exists(Class overridingType, MemberFunction override |
cannotInheritHelper(c, f, overridingType, override) and
exists(MemberFunction override |
cannotInheritHelper(c, f, _, override) and
override.overrides+(f)
)
}

View File

@@ -53,7 +53,7 @@ class Expr extends StmtParent, @expr {
Declaration getEnclosingDeclaration() { result = exprEnclosingElement(this) }
/** Gets a child of this expression. */
Expr getAChild() { exists(int n | result = this.getChild(n)) }
Expr getAChild() { result = this.getChild(_) }
/** Gets the parent of this expression, if any. */
Element getParent() { exprparents(underlyingElement(this), _, unresolveElement(result)) }

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -876,9 +922,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,20 +1526,20 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
pragma[nomagic]
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
bindingset[node1, apc]
pragma[inline_late]
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
@@ -1492,9 +1547,11 @@ private module MkStage<StageSig PrevStage> {
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -1731,8 +1788,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1958,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1980,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -2068,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2333,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2409,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2739,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;
@@ -3749,8 +3822,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4285,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
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()
)
revPartialPathStep(_, 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()
}
pragma[nomagic]
@@ -4230,19 +4301,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
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()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
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

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or
@@ -1391,6 +1391,9 @@ class TypedContentApprox extends MkTypedContentApprox {
/** Gets a typed content approximated by this value. */
TypedContent getATypedContent() { result = getATypedContent(this) }
/** Gets the content. */
ContentApprox getContent() { result = c }
/** Gets the container type. */
DataFlowType getContainerType() { result = t }
@@ -1408,6 +1411,8 @@ abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
abstract boolean toBoolNonEmpty();
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
pragma[nomagic]
TypedContent getAHead() {
exists(TypedContentApprox cont |

View File

@@ -45,6 +45,16 @@ module Consistency {
) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodeAtPosition`. */
predicate uniqueParameterNodeAtPositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodePosition`. */
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
}
private class RelevantNode extends Node {
@@ -101,9 +111,7 @@ module Consistency {
exists(int c |
c =
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not n.hasLocationInfo(_, _, _, _, _) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
) and
msg = "Nodes without location: " + c
@@ -248,6 +256,7 @@ module Consistency {
query predicate uniqueParameterNodeAtPosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodeAtPositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(Node p0 | isParameterNode(p0, c, pos))) and
msg = "Parameters with overlapping positions."
@@ -256,6 +265,7 @@ module Consistency {
query predicate uniqueParameterNodePosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodePositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and
msg = "Parameter node with multiple positions."

View File

@@ -169,19 +169,11 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
*/
predicate modeledTaintStep(Operand nodeIn, Instruction nodeOut) {
exists(CallInstruction call, TaintFunction func, FunctionInput modelIn, FunctionOutput modelOut |
(
nodeIn = callInput(call, modelIn)
or
exists(int n |
modelIn.isParameterDerefOrQualifierObject(n) and
if n = -1
then nodeIn = callInput(call, any(InQualifierObject inQualifier))
else nodeIn = callInput(call, any(InParameter inParam | inParam.getIndex() = n))
)
) and
nodeOut = callOutput(call, modelOut) and
call.getStaticCallTarget() = func and
func.hasTaintFlow(modelIn, modelOut)
|
nodeIn = callInput(call, modelIn) and
nodeOut = callOutput(call, modelOut)
)
or
// Taint flow from one argument to another and data flow from an argument to a

View File

@@ -30,6 +30,7 @@ private newtype TOpcode =
TNegate() or
TShiftLeft() or
TShiftRight() or
TUnsignedShiftRight() or
TBitAnd() or
TBitOr() or
TBitXor() or
@@ -652,6 +653,15 @@ module Opcode {
final override string toString() { result = "ShiftRight" }
}
/**
* The `Opcode` for a `UnsignedShiftRightInstruction`.
*
* See the `UnsignedShiftRightInstruction` documentation for more details.
*/
class UnsignedShiftRight extends BinaryBitwiseOpcode, TUnsignedShiftRight {
final override string toString() { result = "UnsignedShiftRight" }
}
/**
* The `Opcode` for a `BitAndInstruction`.
*

View File

@@ -1204,6 +1204,17 @@ class ShiftRightInstruction extends BinaryBitwiseInstruction {
ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight }
}
/**
* An instruction that shifts its left operand to the right by the number of bits specified by its
* right operand.
*
* Both operands must have an integer type. The result has the same type as the left operand.
* The leftmost bits are zero-filled.
*/
class UnsignedShiftRightInstruction extends BinaryBitwiseInstruction {
UnsignedShiftRightInstruction() { this.getOpcode() instanceof Opcode::UnsignedShiftRight }
}
/**
* An instruction that performs a binary arithmetic operation involving at least one pointer
* operand.

View File

@@ -45,7 +45,7 @@ class Operand extends TStageOperand {
this = reusedPhiOperand(use, def, predecessorBlock, _)
)
or
exists(Instruction use | this = chiOperand(use, _))
this = chiOperand(_, _)
}
/** Gets a textual representation of this element. */
@@ -412,6 +412,9 @@ class CallTargetOperand extends RegisterOperand {
*/
class ArgumentOperand extends RegisterOperand {
override ArgumentOperandTag tag;
/** Gets the `CallInstruction` for which this is an argument. */
CallInstruction getCall() { result.getAnArgumentOperand() = this }
}
/**

View File

@@ -329,12 +329,12 @@ private module Cached {
cached
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
exists(
Alias::VirtualVariable vvar, OldInstruction oldInstr, Alias::MemoryLocation defLocation,
OldBlock defBlock, int defRank, int defOffset, OldBlock useBlock, int useRank
Alias::VirtualVariable vvar, OldInstruction oldInstr, OldBlock defBlock, int defRank,
int defOffset, OldBlock useBlock, int useRank
|
chiInstr = getChi(oldInstr) and
vvar = Alias::getResultMemoryLocation(oldInstr).getVirtualVariable() and
hasDefinitionAtRank(vvar, defLocation, defBlock, defRank, defOffset) and
hasDefinitionAtRank(vvar, _, defBlock, defRank, defOffset) and
hasUseAtRank(vvar, useBlock, useRank, oldInstr) and
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
result = getDefinitionOrChiInstruction(defBlock, defOffset, vvar, _)

View File

@@ -1204,6 +1204,17 @@ class ShiftRightInstruction extends BinaryBitwiseInstruction {
ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight }
}
/**
* An instruction that shifts its left operand to the right by the number of bits specified by its
* right operand.
*
* Both operands must have an integer type. The result has the same type as the left operand.
* The leftmost bits are zero-filled.
*/
class UnsignedShiftRightInstruction extends BinaryBitwiseInstruction {
UnsignedShiftRightInstruction() { this.getOpcode() instanceof Opcode::UnsignedShiftRight }
}
/**
* An instruction that performs a binary arithmetic operation involving at least one pointer
* operand.

View File

@@ -45,7 +45,7 @@ class Operand extends TStageOperand {
this = reusedPhiOperand(use, def, predecessorBlock, _)
)
or
exists(Instruction use | this = chiOperand(use, _))
this = chiOperand(_, _)
}
/** Gets a textual representation of this element. */
@@ -412,6 +412,9 @@ class CallTargetOperand extends RegisterOperand {
*/
class ArgumentOperand extends RegisterOperand {
override ArgumentOperandTag tag;
/** Gets the `CallInstruction` for which this is an argument. */
CallInstruction getCall() { result.getAnArgumentOperand() = this }
}
/**

View File

@@ -298,11 +298,11 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
opcode instanceof Opcode::Store and
resultType = getTypeForPRValue(expr.getType())
or
exists(int startIndex, int elementCount |
exists(int elementCount |
// If the initializer string isn't large enough to fill the target, then
// we have to generate another instruction sequence to store a constant
// zero into the remainder of the array.
zeroInitRange(startIndex, elementCount) and
zeroInitRange(_, elementCount) and
(
// Create a constant zero whose size is the size of the remaining
// space in the target array.

View File

@@ -1204,6 +1204,17 @@ class ShiftRightInstruction extends BinaryBitwiseInstruction {
ShiftRightInstruction() { this.getOpcode() instanceof Opcode::ShiftRight }
}
/**
* An instruction that shifts its left operand to the right by the number of bits specified by its
* right operand.
*
* Both operands must have an integer type. The result has the same type as the left operand.
* The leftmost bits are zero-filled.
*/
class UnsignedShiftRightInstruction extends BinaryBitwiseInstruction {
UnsignedShiftRightInstruction() { this.getOpcode() instanceof Opcode::UnsignedShiftRight }
}
/**
* An instruction that performs a binary arithmetic operation involving at least one pointer
* operand.

View File

@@ -45,7 +45,7 @@ class Operand extends TStageOperand {
this = reusedPhiOperand(use, def, predecessorBlock, _)
)
or
exists(Instruction use | this = chiOperand(use, _))
this = chiOperand(_, _)
}
/** Gets a textual representation of this element. */
@@ -412,6 +412,9 @@ class CallTargetOperand extends RegisterOperand {
*/
class ArgumentOperand extends RegisterOperand {
override ArgumentOperandTag tag;
/** Gets the `CallInstruction` for which this is an argument. */
CallInstruction getCall() { result.getAnArgumentOperand() = this }
}
/**

View File

@@ -329,12 +329,12 @@ private module Cached {
cached
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
exists(
Alias::VirtualVariable vvar, OldInstruction oldInstr, Alias::MemoryLocation defLocation,
OldBlock defBlock, int defRank, int defOffset, OldBlock useBlock, int useRank
Alias::VirtualVariable vvar, OldInstruction oldInstr, OldBlock defBlock, int defRank,
int defOffset, OldBlock useBlock, int useRank
|
chiInstr = getChi(oldInstr) and
vvar = Alias::getResultMemoryLocation(oldInstr).getVirtualVariable() and
hasDefinitionAtRank(vvar, defLocation, defBlock, defRank, defOffset) and
hasDefinitionAtRank(vvar, _, defBlock, defRank, defOffset) and
hasUseAtRank(vvar, useBlock, useRank, oldInstr) and
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
result = getDefinitionOrChiInstruction(defBlock, defOffset, vvar, _)

View File

@@ -67,9 +67,7 @@ class Class = Cpp::Class; // Used for inheritance conversions
predicate getIdentityString = Print::getIdentityString/1;
predicate hasCaseEdge(string minValue, string maxValue) {
exists(Cpp::SwitchCase switchCase | hasCaseEdge(switchCase, minValue, maxValue))
}
predicate hasCaseEdge(string minValue, string maxValue) { hasCaseEdge(_, minValue, maxValue) }
predicate hasPositionalArgIndex(int argIndex) {
exists(Cpp::FunctionCall call | exists(call.getArgument(argIndex))) or

View File

@@ -99,10 +99,10 @@ class MetricClass extends Class {
}
/** Gets any method that accesses some local field. */
Function getAccessingMethod() { exists(Field f | this.accessesLocalField(result, f)) }
Function getAccessingMethod() { this.accessesLocalField(result, _) }
/** Gets any field that is accessed by a local method. */
Field getAccessedField() { exists(Function func | this.accessesLocalField(func, result)) }
Field getAccessedField() { this.accessesLocalField(_, result) }
/** Gets the Henderson-Sellers lack-of-cohesion metric. */
float getLackOfCohesionHS() {
@@ -517,10 +517,10 @@ private predicate dependsOnClassSimple(Class source, Class dest) {
)
or
// a class depends on classes for which a call to its member function is done from a function
exists(MemberFunction target, MemberFunction f, Locatable l |
exists(MemberFunction target, MemberFunction f |
f.getDeclaringType() = source and
f instanceof MemberFunction and
f.calls(target, l) and
f.calls(target, _) and
target instanceof MemberFunction and
target.getDeclaringType() = dest
)

View File

@@ -107,130 +107,34 @@ private FunctionInput getIteratorArgumentInput(Operator op, int index) {
)
}
/**
* A non-member prefix `operator*` function for an iterator type.
*/
private class IteratorPointerDereferenceOperator extends Operator, TaintFunction,
IteratorReferenceFunction {
FunctionInput iteratorInput;
IteratorPointerDereferenceOperator() {
this.hasName("operator*") and
iteratorInput = getIteratorArgumentInput(this, 0)
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = iteratorInput and
output.isReturnValue()
or
input.isReturnValueDeref() and
output.isParameterDeref(0)
}
}
/**
* A non-member `operator++` or `operator--` function for an iterator type.
*
* Note that this class _only_ matches non-member functions. To find both
* non-member and versions, use `IteratorCrementOperator`.
*/
private class IteratorCrementOperator extends Operator, DataFlowFunction {
FunctionInput iteratorInput;
IteratorCrementOperator() {
class IteratorCrementNonMemberOperator extends Operator {
IteratorCrementNonMemberOperator() {
this.hasName(["operator++", "operator--"]) and
iteratorInput = getIteratorArgumentInput(this, 0)
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input = iteratorInput and
output.isReturnValue()
or
input.isParameterDeref(0) and output.isReturnValueDeref()
}
}
/**
* A non-member `operator+` function for an iterator type.
*/
private class IteratorAddOperator extends Operator, TaintFunction {
FunctionInput iteratorInput;
IteratorAddOperator() {
this.hasName("operator+") and
iteratorInput = getIteratorArgumentInput(this, [0, 1])
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = iteratorInput and
output.isReturnValue()
}
}
/**
* A non-member `operator-` function that takes a pointer difference type as its second argument.
*/
private class IteratorSubOperator extends Operator, TaintFunction {
FunctionInput iteratorInput;
IteratorSubOperator() {
this.hasName("operator-") and
iteratorInput = getIteratorArgumentInput(this, 0) and
this.getParameter(1).getUnspecifiedType() instanceof IntegralType // not an iterator difference
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = iteratorInput and
output.isReturnValue()
}
}
/**
* A non-member `operator+=` or `operator-=` function for an iterator type.
*/
class IteratorAssignArithmeticOperator extends Operator {
IteratorAssignArithmeticOperator() {
this.hasName(["operator+=", "operator-="]) and
exists(getIteratorArgumentInput(this, 0))
}
}
private class IteratorAssignArithmeticOperatorModel extends IteratorAssignArithmeticOperator,
DataFlowFunction, TaintFunction {
private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator,
DataFlowFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
input = getIteratorArgumentInput(this, 0) and
output.isReturnValue()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
or
input.isParameterDeref(0) and output.isReturnValueDeref()
or
// reverse flow from returned reference to the object referenced by the first parameter
input.isReturnValueDeref() and
output.isParameterDeref(0)
or
input.isParameterDeref(1) and
output.isParameterDeref(0)
}
}
/**
* A prefix `operator*` member function for an iterator type.
*/
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction {
IteratorPointerDereferenceMemberOperator() {
this.getClassAndName("operator*") instanceof Iterator
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
or
input.isReturnValueDeref() and
output.isQualifierObject()
}
}
/**
* An `operator++` or `operator--` member function for an iterator type.
*
* Note that this class _only_ matches member functions. To find both
* non-member and member versions, use `IteratorCrementOperator`.
*/
class IteratorCrementMemberOperator extends MemberFunction {
IteratorCrementMemberOperator() {
@@ -258,25 +162,49 @@ private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOp
}
/**
* A member `operator->` function for an iterator type.
* A (member or non-member) `operator++` or `operator--` function for an iterator type.
*/
private class IteratorFieldMemberOperator extends Operator, TaintFunction {
IteratorFieldMemberOperator() { this.getClassAndName("operator->") instanceof Iterator }
class IteratorCrementOperator extends Function {
IteratorCrementOperator() {
this instanceof IteratorCrementNonMemberOperator or
this instanceof IteratorCrementMemberOperator
}
}
/**
* A non-member `operator+` function for an iterator type.
*
* Note that this class _only_ matches non-member functions. To find both
* non-member and member versions, use `IteratorBinaryAddOperator`.
*/
class IteratorAddNonMemberOperator extends Operator {
IteratorAddNonMemberOperator() {
this.hasName("operator+") and
exists(getIteratorArgumentInput(this, [0, 1]))
}
}
private class IteratorAddNonMemberOperatorModel extends IteratorAddNonMemberOperator, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
input = getIteratorArgumentInput(this, [0, 1]) and
output.isReturnValue()
}
}
/**
* An `operator+` or `operator-` member function of an iterator class.
*
* Note that this class _only_ matches member functions. To find both
* non-member and member versions, use `IteratorBinaryAddOperator`.
*/
private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, TaintFunction {
class IteratorBinaryArithmeticMemberOperator extends MemberFunction {
IteratorBinaryArithmeticMemberOperator() {
this.getClassAndName(["operator+", "operator-"]) instanceof Iterator
}
}
private class IteratorBinaryArithmeticMemberOperatorModel extends IteratorBinaryArithmeticMemberOperator,
TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
@@ -284,14 +212,84 @@ private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, Tai
}
/**
* An `operator+=` or `operator-=` member function of an iterator class.
* A (member or non-member) `operator+` or `operator-` function for an iterator type.
*/
private class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFunction,
TaintFunction {
class IteratorBinaryArithmeticOperator extends Function {
IteratorBinaryArithmeticOperator() {
this instanceof IteratorAddNonMemberOperator or
this instanceof IteratorSubNonMemberOperator or
this instanceof IteratorBinaryArithmeticMemberOperator
}
}
/**
* A non-member `operator-` function that takes a pointer difference type as its second argument.
*
* Note that this class _only_ matches non-member functions. To find both
* non-member and member versions, use `IteratorBinaryArithmeticOperator` (which also
* includes `operator+` versions).
*/
class IteratorSubNonMemberOperator extends Operator {
IteratorSubNonMemberOperator() {
this.hasName("operator-") and
exists(getIteratorArgumentInput(this, 0)) and
this.getParameter(1).getUnspecifiedType() instanceof IntegralType // not an iterator difference
}
}
private class IteratorSubOperatorModel extends IteratorSubNonMemberOperator, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = getIteratorArgumentInput(this, 0) and
output.isReturnValue()
}
}
/**
* A non-member `operator+=` or `operator-=` function for an iterator type.
*
* Note that this class _only_ matches non-member functions. To find both
* non-member and member versions, use `IteratorAssignArithmeticOperator`.
*/
class IteratorAssignArithmeticNonMemberOperator extends Operator {
IteratorAssignArithmeticNonMemberOperator() {
this.hasName(["operator+=", "operator-="]) and
exists(getIteratorArgumentInput(this, 0))
}
}
private class IteratorAssignArithmeticNonMemberOperatorModel extends IteratorAssignArithmeticNonMemberOperator,
DataFlowFunction, TaintFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
output.isReturnValue()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and output.isReturnValueDeref()
or
// reverse flow from returned reference to the object referenced by the first parameter
input.isReturnValueDeref() and
output.isParameterDeref(0)
or
(input.isParameter(1) or input.isParameterDeref(1)) and
output.isParameterDeref(0)
}
}
/**
* An `operator+=` or `operator-=` member function of an iterator class.
*
* Note that this class _only_ matches member functions. To find both
* non-member and member versions, use `IteratorAssignArithmeticOperator`.
*/
class IteratorAssignArithmeticMemberOperator extends MemberFunction {
IteratorAssignArithmeticMemberOperator() {
this.getClassAndName(["operator+=", "operator-="]) instanceof Iterator
}
}
private class IteratorAssignArithmeticMemberOperatorModel extends IteratorAssignArithmeticMemberOperator,
DataFlowFunction, TaintFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and
output.isReturnValue()
@@ -305,11 +303,88 @@ private class IteratorAssignArithmeticMemberOperator extends MemberFunction, Dat
input.isReturnValueDeref() and
output.isQualifierObject()
or
input.isParameterDeref(0) and
(input.isParameter(0) or input.isParameterDeref(0)) and
output.isQualifierObject()
}
}
/**
* A (member or non-member) `operator+=` or `operator-=` function for an iterator type.
*/
class IteratorAssignArithmeticOperator extends Function {
IteratorAssignArithmeticOperator() {
this instanceof IteratorAssignArithmeticNonMemberOperator or
this instanceof IteratorAssignArithmeticMemberOperator
}
}
/**
* A prefix `operator*` member function for an iterator type.
*
* Note that this class _only_ matches member functions. To find both
* non-member and member versions, use `IteratorPointerDereferenceOperator`.
*/
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction {
IteratorPointerDereferenceMemberOperator() {
this.getClassAndName("operator*") instanceof Iterator
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
or
input.isReturnValueDeref() and
output.isQualifierObject()
}
}
/**
* A non-member prefix `operator*` function for an iterator type.
*
* Note that this class _only_ matches non-member functions. To find both
* non-member and member versions, use `IteratorPointerDereferenceOperator`.
*/
class IteratorPointerDereferenceNonMemberOperator extends Operator, IteratorReferenceFunction {
IteratorPointerDereferenceNonMemberOperator() {
this.hasName("operator*") and
exists(getIteratorArgumentInput(this, 0))
}
}
private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator,
TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = getIteratorArgumentInput(this, 0) and
output.isReturnValue()
or
input.isReturnValueDeref() and
output.isParameterDeref(0)
}
}
/**
* A (member or non-member) prefix `operator*` function for an iterator type.
*/
class IteratorPointerDereferenceOperator extends Function {
IteratorPointerDereferenceOperator() {
this instanceof IteratorPointerDereferenceNonMemberOperator or
this instanceof IteratorPointerDereferenceMemberOperator
}
}
/**
* A member `operator->` function for an iterator type.
*/
private class IteratorFieldMemberOperator extends Operator, TaintFunction {
IteratorFieldMemberOperator() { this.getClassAndName("operator->") instanceof Iterator }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
}
}
/**
* An `operator[]` member function of an iterator class.
*/
@@ -326,17 +401,24 @@ private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
/**
* An `operator=` member function of an iterator class that is not a copy or move assignment
* operator.
*
* The `hasTaintFlow` override provides flow through output iterators that return themselves with
* `operator*` and use their own `operator=` to assign to the container.
*/
private class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
class IteratorAssignmentMemberOperator extends MemberFunction {
IteratorAssignmentMemberOperator() {
this.getClassAndName("operator=") instanceof Iterator and
not this instanceof CopyAssignmentOperator and
not this instanceof MoveAssignmentOperator
}
}
/**
* An `operator=` member function of an iterator class that is not a copy or move assignment
* operator.
*
* The `hasTaintFlow` override provides flow through output iterators that return themselves with
* `operator*` and use their own `operator=` to assign to the container.
*/
private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator,
TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and
output.isQualifierObject()

View File

@@ -27,7 +27,12 @@ private class StdSetConstructor extends Constructor, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// taint flow from any parameter of an iterator type to the qualifier
input.isParameterDeref(this.getAnIteratorParameterIndex()) and
(
// AST dataflow doesn't have indirection for iterators.
// Once we deprecate AST dataflow we can delete this first disjunct.
input.isParameter(this.getAnIteratorParameterIndex()) or
input.isParameterDeref(this.getAnIteratorParameterIndex())
) and
(
output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object
or
@@ -45,7 +50,12 @@ private class StdSetInsert extends TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from last parameter to qualifier and return value
// (where the return value is a pair, this should really flow just to the first part of it)
input.isParameterDeref(this.getNumberOfParameters() - 1) and
(
// AST dataflow doesn't have indirection for iterators.
// Once we deprecate AST dataflow we can delete this first disjunct.
input.isParameter(this.getNumberOfParameters() - 1) or
input.isParameterDeref(this.getNumberOfParameters() - 1)
) and
(
output.isQualifierObject() or
output.isReturnValue()

View File

@@ -38,8 +38,7 @@ private class StdBasicStringIterator extends Iterator, Type {
*/
abstract private class StdStringTaintFunction extends TaintFunction {
/**
* Gets the index of a parameter to this function that is a string (or
* character).
* Gets the index of a parameter to this function that is a string.
*/
final int getAStringParameterIndex() {
exists(Type paramType | paramType = this.getParameter(result).getUnspecifiedType() |
@@ -50,7 +49,14 @@ abstract private class StdStringTaintFunction extends TaintFunction {
paramType instanceof ReferenceType and
not paramType.(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(2).(Type).getUnspecifiedType()
or
)
}
/**
* Gets the index of a parameter to this function that is a character.
*/
final int getACharParameterIndex() {
exists(Type paramType | paramType = this.getParameter(result).getUnspecifiedType() |
// i.e. `std::basic_string::CharT`
paramType = this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType()
)
@@ -79,6 +85,7 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
// taint flow from any parameter of the value type to the returned object
(
input.isParameterDeref(this.getAStringParameterIndex()) or
input.isParameter(this.getACharParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
(
@@ -128,7 +135,7 @@ private class StdStringPush extends StdStringTaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to qualifier
input.isParameterDeref(0) and
input.isParameter(0) and
output.isQualifierObject()
}
}
@@ -180,6 +187,7 @@ private class StdStringAppend extends StdStringTaintFunction {
(
input.isQualifierObject() or
input.isParameterDeref(this.getAStringParameterIndex()) or
input.isParameter(this.getACharParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
(
@@ -210,6 +218,7 @@ private class StdStringInsert extends StdStringTaintFunction {
(
input.isQualifierObject() or
input.isParameterDeref(this.getAStringParameterIndex()) or
input.isParameter(this.getACharParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
(
@@ -236,6 +245,7 @@ private class StdStringAssign extends StdStringTaintFunction {
// flow from parameter to string itself (qualifier) and return value
(
input.isParameterDeref(this.getAStringParameterIndex()) or
input.isParameter(this.getACharParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
(

View File

@@ -133,13 +133,15 @@ abstract class HeuristicAllocationExpr extends Expr {
/**
* Gets a constant multiplier for the allocation size given by `getSizeExpr`,
* in bytes.
* in bytes. This predicate should be used with caution as it can be
* inaccurate for allocations identified using heuristics.
*/
int getSizeMult() { none() }
/**
* Gets the size of this allocation in bytes, if it is a fixed size and that
* size can be determined.
* size can be determined. This predicate should be used with caution as it
* can be inaccurate for allocations identified using heuristics.
*/
int getSizeBytes() { none() }

View File

@@ -158,11 +158,10 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
exists(int arg |
(
arg = getFormatParameterIndex() or
arg >= getFirstFormatArgumentIndex()
) and
input.isParameterDeref(arg) and
arg = getFormatParameterIndex() or
arg >= getFirstFormatArgumentIndex()
|
(input.isParameterDeref(arg) or input.isParameter(arg)) and
output.isParameterDeref(getOutputParameterIndex(_))
)
}

View File

@@ -296,7 +296,7 @@ private predicate analyzableExpr(Expr e) {
or
// Also allow variable accesses, provided that they have SSA
// information.
exists(RangeSsaDefinition def, StackVariable v | e = def.getAUse(v))
exists(RangeSsaDefinition def | e = def.getAUse(_))
or
e instanceof UnsignedBitwiseAndExpr
or

View File

@@ -64,7 +64,7 @@ predicate isInsecureEncryption(string name) { name.regexpMatch(getInsecureAlgori
*/
bindingset[name]
predicate isEncryptionAdditionalEvidence(string name) {
name.toUpperCase().matches("%" + ["CRYPT", "CODE", "CODING", "CBC", "KEY", "CIPHER", "MAC"] + "%")
name.regexpMatch("(?i).*(crypt|code|coding|cbc|key|cipher|mac).*")
}
/**

View File

@@ -14,8 +14,8 @@ import cpp
*/
bindingset[s]
private predicate suspicious(string s) {
s.regexpMatch(".*(password|passwd|accountid|account.?key|accnt.?key|license.?key|trusted).*") and
not s.matches(["%hash%", "%crypt%", "%file%", "%path%", "%invalid%"])
s.regexpMatch("(?i).*(password|passwd|accountid|account.?key|accnt.?key|license.?key|trusted).*") and
not s.regexpMatch("(?i).*(hash|crypt|file|path|invalid).*")
}
/**
@@ -23,7 +23,7 @@ private predicate suspicious(string s) {
*/
class SensitiveVariable extends Variable {
SensitiveVariable() {
suspicious(this.getName().toLowerCase()) and
suspicious(this.getName()) and
not this.getUnspecifiedType() instanceof IntegralType
}
}
@@ -33,7 +33,7 @@ class SensitiveVariable extends Variable {
*/
class SensitiveFunction extends Function {
SensitiveFunction() {
suspicious(this.getName().toLowerCase()) and
suspicious(this.getName()) and
not this.getUnspecifiedType() instanceof IntegralType
}
}

View File

@@ -127,9 +127,9 @@ deprecated private predicate betweenFunctionsValueMoveTo(
not unreachable(src) and
not unreachable(dest) and
(
exists(Call call, Function called, int i |
exists(Call call, int i |
src = call.getArgument(i) and
resolveCallWithParam(call, called, i, dest) and
resolveCallWithParam(call, _, i, dest) and
destFromArg = true
)
or
@@ -151,8 +151,8 @@ deprecated private predicate betweenFunctionsValueMoveTo(
)
or
// If a parameter of type reference is tainted inside a function, taint the argument too
exists(Call call, Function f, int pi, Parameter p |
resolveCallWithParam(call, f, pi, p) and
exists(Call call, int pi, Parameter p |
resolveCallWithParam(call, _, pi, p) and
p.getType() instanceof ReferenceType and
src = p and
dest = call.getArgument(pi) and

View File

@@ -34,7 +34,7 @@ class Stmt extends StmtParent, @stmt {
}
/** Gets a child of this statement. */
Element getAChild() { exists(int n | result = this.getChild(n)) }
Element getAChild() { result = this.getChild(_) }
/** Gets the parent of this statement, if any. */
StmtParent getParent() { stmtparents(underlyingElement(this), _, unresolveElement(result)) }

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