Compare commits

...

803 Commits

Author SHA1 Message Date
Nick Rolfe
11bcad37af Ruby: update crate versions 2021-10-27 18:12:12 +01:00
Shati Patel
c9b50f3c2f Merge pull request #6981 from github/aibaars/ruby-lgtm-links
Ruby: update lgtm.com query console links
2021-10-27 17:18:08 +01:00
Arthur Baars
f496336a0d Ruby: update lgtm.com query console links 2021-10-27 18:08:11 +02:00
Nick Rolfe
06303b103f Merge pull request #6979 from github/nickrolfe/revert-crate-updates
Ruby: revert crate updates
2021-10-27 16:53:19 +01:00
Nick Rolfe
7a5e8f1756 Ruby: update Cargo.lock 2021-10-27 16:21:33 +01:00
Nick Rolfe
ff7826dd96 Revert "Update tracing-subscriber requirement from 0.2 to 0.3 in /ruby/generator"
This reverts commit 4cedb43a54.
2021-10-27 16:21:33 +01:00
Nick Rolfe
fc1f874f92 Revert "Update tracing-subscriber requirement from 0.2 to 0.3 in /ruby/extractor"
This reverts commit e9da027539.
2021-10-27 16:21:33 +01:00
Arthur Baars
dc24361f89 Merge pull request #6974 from github/nickrolfe/Cargo_lock
Ruby: update Cargo.lock
2021-10-27 13:47:22 +02:00
Nick Rolfe
0a89028663 Ruby: update Cargo.lock 2021-10-27 11:43:09 +01:00
Anders Schack-Mulligen
4a67ac5e0b Merge pull request #4991 from JLLeitschuh/feat/JLL/early_ratpack_support
Java: Simple support for Ratpack HTTP Framework
2021-10-27 09:25:52 +02:00
Joe Farebrother
02b440b0ed Merge pull request #6599 from joefarebrother/android-sensitive-communication
Java: Promote android sensitive broadcast query
2021-10-26 13:48:58 +01:00
CodeQL CI
e5e1046c81 Merge pull request #6962 from asgerf/js/template-db-constraint-err
Approved by erik-krogh
2021-10-26 13:43:57 +01:00
Jonathan Leitschuh
21aeee6378 Actually remove the last non-ascii quote from Promise
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-26 08:28:44 -04:00
Alexander Eyers-Taylor
3bae95a93a Merge pull request #6939 from edoardopirovano/bump-version
Fix version number in language reference
2021-10-26 13:11:30 +01:00
Anders Schack-Mulligen
90bebaa5a9 Merge pull request #6960 from erik-krogh/useSetLiteral
use set literal instead of big disjunction of literals
2021-10-26 14:06:05 +02:00
Anders Schack-Mulligen
ba95d46ec3 Apply suggestions from code review
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2021-10-26 14:04:13 +02:00
Erik Krogh Kristensen
090fb2df10 Merge pull request #6857 from erik-krogh/fixPipes
JS: skip pipes and other special files when determining which files to extract
2021-10-26 13:59:40 +02:00
Mathias Vorreiter Pedersen
4a58349fcd Merge pull request #6961 from MathiasVP/fix-join-order-in-in-def-dominance-frontier
C#: Fix join order in `inDefDominanceFrontier`
2021-10-26 12:55:31 +01:00
Edoardo Pirovano
6a3de20e7a Fix version number in language reference 2021-10-26 12:53:48 +01:00
Erik Krogh Kristensen
a3c55c2aec use set literal instead of big disjunction of literals 2021-10-26 12:55:25 +02:00
Rasmus Wriedt Larsen
2b9edd7ff6 Merge pull request #6952 from github/aibaars/generate-code-scanning-query-list
Add Ruby to generate-code-scanning-query-list.py and make the script faster
2021-10-26 10:49:24 +02:00
Mathias Vorreiter Pedersen
67fd38f328 C#/Ruby: Use a 'noinline' instead of a 'only_bind_into'. 2021-10-26 09:41:52 +01:00
Anders Schack-Mulligen
3d1b617101 Merge pull request #6959 from igfoo/igfoo/bbStmts
Java: Make a test output a bit more readable
2021-10-26 08:42:53 +02:00
Mathias Vorreiter Pedersen
4b137ede0e Ruby: Sync identical files. 2021-10-25 22:03:44 +01:00
Mathias Vorreiter Pedersen
e2d3474563 Merge branch 'main' into fix-join-order-in-in-def-dominance-frontier 2021-10-25 22:02:35 +01:00
Mathias Vorreiter Pedersen
9145382660 C#: Sync identical files. 2021-10-25 21:55:28 +01:00
Mathias Vorreiter Pedersen
ff35100d52 C#: Fix join order in 'inDefDominanceFrontier'. 2021-10-25 21:55:09 +01:00
Henry Mercer
3284953192 Merge pull request #6958 from github/henrymercer/rename-atm-query-pack
JS: [Internal only] Rename ATM query pack for consistency with other packs
2021-10-25 20:16:40 +01:00
Ian Lynagh
f73f418a97 Java: Make a test output a bit more readable
Now the nodes are in index order, and the indices are aligned.
2021-10-25 18:48:19 +01:00
Henry Mercer
7e0e35f364 Rename ATM query pack for consistency with other packs 2021-10-25 17:32:25 +01:00
Jonathan Leitschuh
ebe2c26f4d Remove the last non-ascii quote from Promise
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-25 11:30:12 -04:00
Nick Rolfe
db3c99d64d Merge pull request #6954 from github/nickrolfe/ruby-labeler
Automatically label Ruby PRs
2021-10-25 15:44:30 +01:00
Nick Rolfe
096c207b3e Automatically label Ruby PRs 2021-10-25 15:29:20 +01:00
CodeQL CI
3fc6e2b294 Merge pull request #6941 from RasmusWL/add-missing-noinline
Approved by tausbn
2021-10-25 15:23:37 +01:00
CodeQL CI
b5554da496 Merge pull request #6924 from asgerf/js/skip-files-with-unsupported-encoding
Approved by esbena
2021-10-25 14:48:38 +01:00
Nick Rolfe
7308f75b78 Merge pull request #6951 from github/nickrolfe/remove-workspace
Ruby: remove VS Code workspace
2021-10-25 14:29:06 +01:00
Joe Farebrother
6dac86b9be Fix unneeded import and spelling mistake 2021-10-25 14:11:00 +01:00
Arthur Baars
dcf71c4f9a Ruby: update generate-code-scanning-query-list.py 2021-10-25 15:04:34 +02:00
Arthur Baars
a6ac2e73a1 Speed up generate-code-scanning-query-list.py
Use 'codeql execute cli-server' to avoid repeated JVM startup overhead
2021-10-25 15:03:28 +02:00
Nick Rolfe
779e24eb73 Ruby: remove VS Code workspace 2021-10-25 13:12:31 +01:00
Nick Rolfe
fb79886fe7 Merge pull request #6944 from github/dependabot/cargo/ruby/extractor/tracing-subscriber-0.3
Update tracing-subscriber requirement from 0.2 to 0.3 in /ruby/extractor
2021-10-25 12:50:48 +01:00
Nick Rolfe
b93be42421 Merge pull request #6943 from github/dependabot/cargo/ruby/generator/tracing-subscriber-0.3
Update tracing-subscriber requirement from 0.2 to 0.3 in /ruby/generator
2021-10-25 12:50:26 +01:00
Anders Schack-Mulligen
c48dd57d85 Merge pull request #6938 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-10-25 13:43:54 +02:00
Joe Farebrother
0c1af2411b Write intent in lowercase consistently
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-25 12:22:49 +01:00
Anders Schack-Mulligen
5709365c0f Merge pull request #6921 from igfoo/igfoo/types
Java: Replace @type with more specific types
2021-10-25 13:15:12 +02:00
dependabot[bot]
e9da027539 Update tracing-subscriber requirement from 0.2 to 0.3 in /ruby/extractor
Updates the requirements on [tracing-subscriber](https://github.com/tokio-rs/tracing) to permit the latest version.
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.2.0...tracing-subscriber-0.3.0)

---
updated-dependencies:
- dependency-name: tracing-subscriber
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-25 10:40:34 +00:00
dependabot[bot]
4cedb43a54 Update tracing-subscriber requirement from 0.2 to 0.3 in /ruby/generator
Updates the requirements on [tracing-subscriber](https://github.com/tokio-rs/tracing) to permit the latest version.
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.2.0...tracing-subscriber-0.3.0)

---
updated-dependencies:
- dependency-name: tracing-subscriber
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-25 10:40:28 +00:00
Arthur Baars
afc7867c98 Merge pull request #6942 from github/aibaars/patch-10
Merge codeql-ruby into codeql
2021-10-25 12:33:34 +02:00
Asger Feldthaus
bfb1da55d6 JS: Bump extractor version string 2021-10-25 11:49:56 +02:00
Asger Feldthaus
f3e2b0b946 JS: Avoid using non-existent attribute as parent 2021-10-25 11:49:56 +02:00
Asger Feldthaus
ac62379b17 JS: Add TRAP test 2021-10-25 11:49:39 +02:00
github-actions[bot]
2257d0475a Add changed framework coverage reports 2021-10-25 00:09:34 +00:00
Arthur Baars
4f79398342 Merge branch 'main' of github.com:github/codeql into 'main'
Conflicts:
	docs/codeql/query-help/codeql-cwe-coverage.rst
2021-10-22 21:51:25 +02:00
Tom Hvitved
f020b2e437 Merge pull request #335 from github/hmac/self-flow 2021-10-22 19:14:20 +02:00
Jonathan Leitschuh
5eb28398f0 Remove non-ASCII characters from Promise.java
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-22 10:52:46 -04:00
Nick Rolfe
3851a27fc1 Merge pull request #358 from github/external-control-file-path
Add rb/path-injection query
2021-10-22 15:38:39 +01:00
Tom Hvitved
7648815f1f Merge pull request #6936 from hvitved/csharp/delegate-conversion-join-order
C#: Improve join-order in `defaultDelegateConversion`
2021-10-22 15:10:20 +02:00
Tom Hvitved
61d7cdeec0 Data flow: Assign empty locations to summary nodes 2021-10-22 14:48:33 +02:00
Harry Maclean
87df3a0a99 Minor refactor 2021-10-22 11:44:38 +01:00
hubwriter
12e56ec9e6 Merge pull request #6887 from github/hubwriter/codeql-ruby-support
Docs: Updates for Ruby support
2021-10-22 11:21:49 +01:00
Nick Rolfe
d4cee73720 Add taint summaries for ActiveStorage::Filename 2021-10-22 11:15:42 +01:00
Henry Mercer
02b1fe27d2 Merge pull request #6907 from github/henrymercer/add-experimental-atm-libraries
JS: [Internal only] Add experimental libraries and queries for adaptive threat modeling
2021-10-22 11:02:09 +01:00
Harry Maclean
aa8607009b Update test fixtures 2021-10-22 10:56:34 +01:00
Harry Maclean
336bd15d2f Override isCapturedAccess for self variables
Many `self` reads are synthesised from method calls with an implicit
`self` receiver. Synthesised nodes have no `toGenerated` result, which
the default definition of `isCapturedAccess` uses to determine if a
variable's scope matches the access's scope.

Hence we override the definition to properly identify accesses like the
call `puts` (below) as captured reads of a `self` variable defined in a
parent scope.

In other words, `puts x` is short for `self.puts x` and the `self`
refers to its value in the scope of the module `Foo`.

```ruby
module Foo
  MY_PROC = -> (x) { puts x }
end
```

We also have to update the SSA `SelfDefinition` to exclude captured
`self` variables.
2021-10-22 10:56:34 +01:00
Harry Maclean
f1add388a0 Synthesise writes to self for classes/modules
This requires changing the CFG trees for classes and modules from
post-order to pre-order so that we can place the writes at the root node
of the tree, to prevent them overlapping with reads in the body of the
class/module.

We need to do this because classes and modules don't define their own
basic block, but re-use the surrounding one. This problem doesn't occur
for `self` variables in methods because each method has its own basic
block and we can place the write on the entry node of the bock.
2021-10-22 10:56:34 +01:00
Joe Farebrother
c89178c0e8 Apply suggestions from code review
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2021-10-22 10:54:57 +01:00
Tony Torralba
1333f67a69 Merge pull request #6917 from JLLeitschuh/feat/JLL/jdk_lambda_collections_model_tracking
[Java] JDK Collection lambda models
2021-10-22 10:26:50 +02:00
Tom Hvitved
4e40337d02 C#: Improve join-order in defaultDelegateConversion 2021-10-22 10:12:18 +02:00
Arthur Baars
4f72d0853a Merge pull request #375 from github/rc/3.3
Merge rc/3.3 into main
2021-10-21 18:16:57 +02:00
Joe Farebrother
2d368a7d9a Remove redundant imports from ExternalFlow 2021-10-21 16:48:53 +01:00
Joe Farebrother
a9dde419d2 Fix up test 2021-10-21 16:46:07 +01:00
Taus
562a57b75b Merge pull request #6928 from RasmusWL/diagnostic-as-warning
Python: Improve SARIF severity level reporting of extractor diagnostics
2021-10-21 13:54:01 +02:00
Nick Rolfe
5734f51792 Merge remote-tracking branch 'origin/main' into external-control-file-path 2021-10-21 10:58:38 +01:00
Rasmus Wriedt Larsen
852e9875bd Python: Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-10-21 10:24:34 +02:00
Edoardo Pirovano
1fe772a2ab Merge pull request #6896 from edoardopirovano/fix-version-trailing
Language reference: Fix when trailing commas are allowed
2021-10-21 00:02:02 +01:00
Aditya Sharad
174df98762 Merge pull request #6929 from github/esbena-patch-5
Mention default JavaScript Autobuilder excludes
2021-10-20 15:47:51 -07:00
Esben Sparre Andreasen
a1ce81c3d7 Update creating-codeql-databases.rst 2021-10-20 23:00:46 +02:00
Arthur Baars
f9f0fab0d0 Merge pull request #374 from github/aibaars/sync-codeql
Sync with `github/codeql:main`
2021-10-20 22:38:46 +02:00
Ian Lynagh
830f81bfdb Java: Autoformat 2021-10-20 17:45:01 +01:00
Joe Farebrother
3e3503a763 Fix failing checks 2021-10-20 17:25:38 +01:00
Joe Farebrother
b6c584cb70 Update docs 2021-10-20 17:09:59 +01:00
Joe Farebrother
447e06d92a Rename from SensitiveBroadcast to SensitiveCommmunication 2021-10-20 17:09:59 +01:00
Joe Farebrother
54e9c49080 Remove SendBroadcastMethodAccess 2021-10-20 17:09:59 +01:00
Joe Farebrother
e02be6cf93 Add additional sinks 2021-10-20 17:09:59 +01:00
Joe Farebrother
e616122982 Rename parameter 2021-10-20 17:09:59 +01:00
Joe Farebrother
fede77a934 Rename some utility methods 2021-10-20 17:09:59 +01:00
Joe Farebrother
069d6627b5 Improve sanitizers 2021-10-20 17:09:59 +01:00
Joe Farebrother
174ac3d6c3 Move to correct directory 2021-10-20 17:09:59 +01:00
Joe Farebrother
c3d1165c5f Revert change to argument handling 2021-10-20 17:09:58 +01:00
Joe Farebrother
6a2346ec33 Clean up sink definition 2021-10-20 17:09:58 +01:00
Joe Farebrother
daf6ac2584 Update tests to InlineFlowTest 2021-10-20 17:09:58 +01:00
Joe Farebrother
52ca6b93e3 Make things private where possible 2021-10-20 17:09:58 +01:00
Joe Farebrother
351e67c639 Fix qhelp 2021-10-20 17:09:58 +01:00
Joe Farebrother
06a30bf822 Add change note 2021-10-20 17:09:58 +01:00
Joe Farebrother
b112189530 Update docs 2021-10-20 17:09:58 +01:00
Joe Farebrother
224d679722 Add Sticky broadcast sinks 2021-10-20 17:09:57 +01:00
Joe Farebrother
ef7125e21a Simplify sink definitions using local flow 2021-10-20 17:09:57 +01:00
Joe Farebrother
d7c7776495 Add additional models; fix up tests 2021-10-20 17:09:57 +01:00
Joe Farebrother
ae461bcfe4 Switch to inline expectations tests 2021-10-20 17:09:57 +01:00
Joe Farebrother
4012866c6f Allow arbitrary read steps at the sink 2021-10-20 17:09:57 +01:00
Joe Farebrother
bae0da8851 Remove existing get methods 2021-10-20 17:09:57 +01:00
Joe Farebrother
1e8dd7ae40 Use subclasses of context for sinks 2021-10-20 17:09:57 +01:00
Joe Farebrother
143920efca Movee query logic to a qll file 2021-10-20 17:09:57 +01:00
Joe Farebrother
c68a7077d7 Move query and tests out of experimental 2021-10-20 17:09:56 +01:00
Rasmus Wriedt Larsen
8167e83ae5 Python: Fix tests 2021-10-20 17:58:03 +02:00
Jonathan Leitschuh
cce3aad62e Remove non-ASCII characters from Handler.java
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-20 11:34:59 -04:00
Rasmus Wriedt Larsen
d0fd907582 Python: Add change-note
I reworded this slightly from what was done in C++, such that I can
completely stand behind what it says.
2021-10-20 17:03:55 +02:00
Rasmus Wriedt Larsen
8f28684d10 Python: Rename ExtractionErrors.ql -> ExtractionWarnings.ql 2021-10-20 17:01:33 +02:00
Rasmus Wriedt Larsen
605494c3d1 Python: Treat SyntaxErrors as warnings in diagnostics
Rename going to happen in second commit, so git doesn't get too confused

I don't actually recall where to lookup that warning is 1, and error is
2, but I took this from
https://github.com/github/codeql/pull/6830/files#diff-460fc20823ced3b074784db804f2d4d6cfcad4f23fe5d264dc7496c782629a2eR121-R123
2021-10-20 16:59:00 +02:00
Mathias Vorreiter Pedersen
7feab27bf4 Merge pull request #6926 from geoffw0/setliterals2
C++: Use set literals (more).
2021-10-20 14:58:06 +01:00
Arthur Baars
630ee17613 Ruby: sync-files and add allowParameterReturnInSelf() 2021-10-20 15:39:46 +02:00
Arthur Baars
0bec8987b6 Merge remote-tracking branch 'codeql/main' into 'main' 2021-10-20 15:38:59 +02:00
Geoffrey White
da412178ce C++: Use set literals (more). 2021-10-20 14:18:27 +01:00
Harry Maclean
356828cd51 Update stored XSS fixture
The change to `self` modelling finds more true positives in this query.
2021-10-20 13:30:51 +01:00
Nick Rolfe
16c62d22de Add change-note for rb/path-injection 2021-10-20 13:19:49 +01:00
Nick Rolfe
e367832637 Import Frameworks.qll in Summaries module 2021-10-20 13:11:50 +01:00
hubwriter
8f15dc4bd0 Add 'requires glibc 2.17' in supported languages table 2021-10-20 12:48:20 +01:00
Nick Rolfe
86da3c2db3 Add rb/path-injection query 2021-10-20 12:31:16 +01:00
Tom Hvitved
19589bef27 Merge pull request #6777 from hvitved/dataflow/summary-clear-modelling
Data flow: Rework `SummarizedCallable::clearsContent/2`
2021-10-20 13:23:56 +02:00
Ian Lynagh
25b5601da9 Java: Add a changenote to RefType -> ClassOrInterface 2021-10-20 12:21:08 +01:00
Ian Lynagh
25fcae1c51 Java: Make some types more specific
Where we used to use RefType, we now use ClassOrInterface.
2021-10-20 12:18:20 +01:00
hubwriter
aaa5046533 Add beta note to page Calum added 2021-10-20 11:17:38 +01:00
Asger Feldthaus
fa0ce5380b JS: Skip files with unsupported file encoding 2021-10-20 12:16:50 +02:00
Tom Hvitved
f9fb046e9f C#: Update expected test output after rebase 2021-10-20 12:15:27 +02:00
Tom Hvitved
29cdc8a49a Java: Update expected test output after rebase 2021-10-20 12:11:59 +02:00
hubwriter
dd31d5ffb3 Merge branch 'main' into hubwriter/codeql-ruby-support 2021-10-20 11:08:59 +01:00
Tom Hvitved
0bf5238f39 Update QL doc for allowParameterReturnInSelf 2021-10-20 12:08:58 +02:00
Tom Hvitved
53d4d72fe5 C#: Simplify SummarizedCallableDefaultClearsContent 2021-10-20 12:08:58 +02:00
Tom Hvitved
dd138b0429 Address review comments 2021-10-20 12:08:58 +02:00
Tom Hvitved
ec5d8ab2db Java: Restrict use-use flow 2021-10-20 12:08:57 +02:00
Tom Hvitved
a1511e13d8 Data flow: Sync files 2021-10-20 12:08:57 +02:00
Tom Hvitved
1196d0c624 C#: Rework SummarizedCallable::clearsContent/2 2021-10-20 12:08:57 +02:00
Calum Grant
ed73d9bab4 Merge pull request #6860 from github/ruby-docs
Ruby documentation
2021-10-20 10:47:05 +01:00
Tom Hvitved
f1f7930529 Make all self nodes LocalSourceNodes 2021-10-20 11:43:50 +02:00
Tom Hvitved
94f0f8daf2 Make SelfVariableAccess a sub type of LocalVariableAccess 2021-10-20 11:43:44 +02:00
Harry Maclean
e0b2d88377 Remove redundant import 2021-10-20 10:41:17 +01:00
Harry Maclean
c437fd50a4 Update test fixtures
Some of these look a bit suspicious, so need to double check them before
merging.
2021-10-20 10:39:36 +01:00
Harry Maclean
c71f538a5a Extend the scope of self variables
`self` variables are scoped to methods, modules, classes and the
top-level of the program. Prior to this change, they were treated as
being scoped just to methods.

This change means we (once again) correctly synthesise `self` receivers
for method calls in class bodies, module bodies and at the top-level.
2021-10-20 09:43:23 +01:00
Harry Maclean
647485acde Don't omit self from uninitialized writes
We can safely create uninitialized writes for `self` variables, because
they appear at index -1 in the entry block of a method, and are
immediately overwritten by a write to `self` at index 0. As a result,
they are not live and will be pruned from the CFG.
2021-10-20 09:43:22 +01:00
Tom Hvitved
446eb13471 Minor adjustments to SSA library for self variables 2021-10-20 09:43:21 +01:00
Harry Maclean
0d39a15786 Model implicit reads of self variables
We already synthesise `self` nodes for method calls with no receiver.
This change creates read accesses for each of these synthesised nodes.
2021-10-20 09:43:20 +01:00
Harry Maclean
e7a3050fb2 Improve the modelling of self variables.
We model `self` variables by inserting a write at the start of every
method body. We then treat them as local variables that are alive for
the extent of the method body.
2021-10-20 09:43:19 +01:00
Tamás Vajk
9331b3538d Merge pull request #6914 from tamasvajk/feature/improve-csv-pr-commenter
Introduce foldable region in CSV coverage PR comments
2021-10-20 08:45:55 +02:00
Ian Lynagh
9fbff1b4c1 Java: Add an upgrade script 2021-10-20 00:34:47 +01:00
Jonathan Leitschuh
d4b18fe6a3 [Java] JDK Collection lambda models
Adds support for data flow tracking through simple JDK collection
functional APIs.
 - `Iterable::forEach`
 - `Iterator::forEachRemaining`
 - `Map::forEach`

Replaces #5871

Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-19 15:57:58 -04:00
Ian Lynagh
90299033d1 Java: Replace @type with more specific types 2021-10-19 20:23:53 +01:00
Jonathan Leitschuh
584c27a2f8 Move CollectionPassingTest to correct directory 2021-10-19 11:44:12 -04:00
Jonathan Leitschuh
8231907116 Ratpack code cleanup from code review 2021-10-19 11:42:35 -04:00
Calum Grant
112d408fb9 Address review comments. 2021-10-19 16:30:54 +01:00
Chris Smowton
233a3346a8 Merge pull request #6240 from haby0/java/UnsafeUrlForward
[Java] CWE-552: Unsafe url forward
2021-10-19 16:18:23 +01:00
Jonas Jensen
7015be7cad Merge pull request #6916 from geoffw0/fixnotbound
C++: Fix unbound variables in PrivateCleartextWrite.qll.
2021-10-19 16:46:42 +02:00
Geoffrey White
38257a58f0 C++: Fix unbound variables in PrivateCleartextWrite.qll. 2021-10-19 15:01:32 +01:00
Tom Hvitved
3f396ac10e Merge pull request #371 from github/hvitved/dataflow/arg-sugar
Data flow: Fix bug for sugared call arguments
2021-10-19 15:48:21 +02:00
Chris Smowton
057d0fb7e0 Rewrite query to use shared StringPrefixes library 2021-10-19 14:45:38 +01:00
Tamás Vajk
12d7f0c9e2 Merge pull request #6913 from tamasvajk/feature/improve-stubbing
C#: Remove cartesian product in stubbing (GeneratedType::getStub)
2021-10-19 15:13:26 +02:00
Chris Smowton
8a4fa0a7e2 Copyedit 2021-10-19 12:50:17 +01:00
haby0
9d9a7abd06 Fix 2021-10-19 12:50:03 +01:00
haby0
283376eb19 Modify the model 2021-10-19 12:49:08 +01:00
haby0
679652e63a Modify Sanitizer 2021-10-19 12:49:08 +01:00
haby0
952b34a163 Eliminate FP 2021-10-19 12:49:08 +01:00
haby0
d0eec1e381 Add CWE-552-UnsafeUrlForward 2021-10-19 12:49:07 +01:00
Tamas Vajk
70ffbae091 Introduce foldable region in CSV coverage PR comments 2021-10-19 13:34:25 +02:00
Anders Schack-Mulligen
662852bd1d Merge pull request #6859 from smowton/smowton/admin/factor-string-prefix
Java: Factor out string prefix logic
2021-10-19 13:32:52 +02:00
Henry Mercer
548a344d34 JS: Implement suggestions from review
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com>
2021-10-19 12:00:40 +01:00
Tamas Vajk
c7c35401e0 C#: Remove cartesian product in stubbing (GeneratedType::getStub) 2021-10-19 12:56:23 +02:00
Chris Smowton
d46b897492 Add explicit this 2021-10-19 11:32:24 +01:00
Chris Smowton
beaa1cffd2 Make import private 2021-10-19 11:28:56 +01:00
Chris Smowton
3bf9abb4ce Avoid ambiguous term 'successor'. 2021-10-19 11:28:56 +01:00
Chris Smowton
0d66cebfba Autoformat 2021-10-19 11:28:56 +01:00
Chris Smowton
3c25301593 Extend documentation 2021-10-19 11:28:55 +01:00
Chris Smowton
d0d17e3b84 Make import private 2021-10-19 11:28:55 +01:00
Chris Smowton
b71920209e Factor out string prefix logic 2021-10-19 11:28:54 +01:00
Anders Schack-Mulligen
b975e12f41 Merge pull request #6912 from aschackmull/java/minor-perf-fix
Java: Fix bad join-order.
2021-10-19 12:13:26 +02:00
Rasmus Wriedt Larsen
386c7e3a12 Python: Add missing pragma[noinline] 2021-10-19 11:55:51 +02:00
Rasmus Wriedt Larsen
b0af805460 Merge pull request #6899 from thepurpleowl/patch-1
Python SignatureOverriddenMethod: Rmv duplicate condition
2021-10-19 11:24:01 +02:00
Anders Schack-Mulligen
90a50e7ca9 Java: Fix bad join-order. 2021-10-19 10:55:52 +02:00
Anders Schack-Mulligen
6508afe824 Merge pull request #6900 from Marcono1234/marcono1234/MemberRefExpr-receiver-type
Java: Add `MemberRefExpr.getReceiverType()`
2021-10-19 10:49:15 +02:00
hubwriter
6f34735f64 Update docs/codeql/writing-codeql-queries/creating-path-queries.rst 2021-10-19 09:27:54 +01:00
Jonathan Leitschuh
db2892b9ea Resove taint tracking issues from asMultimap
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 14:30:46 -04:00
Henry Mercer
4d7a8285ad JS: Initial commit of Adaptive Threat Modeling 2021-10-18 17:24:24 +01:00
Jonathan Leitschuh
5a2bdc9a0f Jackson taint tracking of elements
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:11 -04:00
Jonathan Leitschuh
8fecc158ff Add support for Map.forEach
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:11 -04:00
Jonathan Leitschuh
23e60e2c52 Add full integration test for Ratpack example
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:11 -04:00
Jonathan Leitschuh
ebbbda70c0 Ratpack tests all passing
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:11 -04:00
Jonathan Leitschuh
fe374f5e9c Ratpack: Add support for Promise::apply
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:10 -04:00
Jonathan Leitschuh
6562ac3680 Ratpack conversion to new lambda model
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:10 -04:00
Jonathan Leitschuh
4f90f0a748 Begin refactoring Ratpack to use functional taint tracking
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
2021-10-18 12:21:10 -04:00
Jonathan Leitschuh
6497a61c1d Ratpack: Drop support for flatMap like methods 2021-10-18 12:21:10 -04:00
Jonathan Leitschuh
af90b00e63 Ratpack: Release note and typo fix 2021-10-18 12:21:10 -04:00
Jonathan Leitschuh
901631ceb8 Ratpack Promise add support for apply method 2021-10-18 12:21:10 -04:00
Jonathan Leitschuh
b9dc3d0cfe Ratpack: Better support for Promise API 2021-10-18 12:21:09 -04:00
Jonathan Leitschuh
cdfdcc66bd Ratpack fix formatting and non-ascii characters 2021-10-18 12:21:09 -04:00
Jonathan Leitschuh
a3b1736a73 Ratpack improve support for parsing types 2021-10-18 12:21:09 -04:00
Jonathan Leitschuh
ac185d9bd5 Remove RatpackGetRequestDataMethod 2021-10-18 12:21:09 -04:00
Jonathan Leitschuh
563e5690df Refactor Ratpack to use CSV format 2021-10-18 12:21:09 -04:00
Jonathan Leitschuh
4f658df0ac Apply suggestions from code review
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
2021-10-18 12:21:09 -04:00
Jonathan Leitschuh
18c74c5030 Simplify Ratpack API using standard abstract classes 2021-10-18 12:21:08 -04:00
Jonathan Leitschuh
b2e3df29b3 Add support for Promise.value and Promise::flatMap 2021-10-18 12:21:08 -04:00
Jonathan Leitschuh
b2ad128beb Refactors Ratpack lambda taint tracking to use generic API 2021-10-18 12:21:08 -04:00
Jonathan Leitschuh
170657b9a4 Add additional Ratpack test and improve Promise based dataflow tracking 2021-10-18 12:21:08 -04:00
Jonathan Leitschuh
dabf00e8b4 Add Tests to Ratpack Framework Support 2021-10-18 12:21:08 -04:00
Jonathan Leitschuh
f5c3723a99 Java: Simple support for Ratpack HTTP Framework 2021-10-18 12:21:08 -04:00
Marcono1234
86d53931aa Java: Improve MemberRefExpr.getReceiverType() documentation 2021-10-18 18:20:22 +02:00
Geoffrey White
3f3c79f48f Merge pull request #6884 from geoffw0/setliterals
Replace or chains with set literals.
2021-10-18 16:46:55 +01:00
Anders Schack-Mulligen
b67032d1cc Merge pull request #6891 from erik-krogh/fix-java-this
add explicit this qualifier on all of java
2021-10-18 17:13:37 +02:00
Tom Hvitved
c57b7c5b2b Data flow: Restrict ExprReturnNode to nodes from the body of the callable 2021-10-18 17:01:30 +02:00
Tom Hvitved
a10bde5795 Merge pull request #6872 from hvitved/dataflow/path-into-callable0-join
Data flow: Performance tweaks
2021-10-18 16:25:10 +02:00
Taus
8e68eae83d Merge pull request #5463 from jorgectf/jorgectf/python/headerInjection
Python: Add Header Injection query
2021-10-18 15:16:14 +02:00
Tom Hvitved
e6954292aa Address review comments 2021-10-18 14:09:44 +02:00
Anders Schack-Mulligen
91ea064980 Sync 2021-10-18 14:04:50 +02:00
Anders Schack-Mulligen
df9836cce0 Work around compiler bug. 2021-10-18 14:04:16 +02:00
Tom Hvitved
397b8345e0 Data flow: Fix bug for sugared call arguments 2021-10-18 13:48:11 +02:00
Tom Hvitved
0de27bbc7e Data flow: Add ArgumentNode test 2021-10-18 13:47:50 +02:00
Jonas Jensen
493a37ba5e Merge pull request #6903 from MathiasVP/remove-implicit-this-for-cpp
C++: Remove uses of implicit `this`
2021-10-18 13:41:30 +02:00
Ian Lynagh
9371737331 Merge pull request #6894 from igfoo/igfoo/exprs
Java: Don't use dbscheme tables in CloseType.qll
2021-10-18 12:04:11 +01:00
Ian Lynagh
54d2028920 Update java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-10-18 10:12:01 +01:00
Mathias Vorreiter Pedersen
ea67ca22a9 C++: Undo changes to shared dataflow files. 2021-10-18 09:00:00 +01:00
Tony Torralba
5216bbab93 Merge pull request #6835 from atorralba/atorralba/fix-local-and-remote-flow-tests
Java: Use InlineExpectationsTest for local and remote flow tests
2021-10-18 09:33:57 +02:00
Tom Hvitved
47ae76fb7d Merge pull request #6890 from hvitved/csharp/nullable-default-param
C#: Handle `Nullable<T>` default parameter values in assemblies
2021-10-18 08:55:02 +02:00
Tony Torralba
e3b46f25a5 Merge branch 'main' into atorralba/fix-local-and-remote-flow-tests 2021-10-18 08:52:37 +02:00
Marcono1234
43b7bc52ca Java: Add MemberRefExpr.getReceiverType() 2021-10-18 00:26:19 +02:00
Mathias Vorreiter Pedersen
af6a21f5d9 Merge pull request #6893 from geoffw0/nullterm
C++: Disable the two null termination queries enabled by 6794.
2021-10-17 22:14:10 +01:00
Surya Prakash Sahu
2871bdb206 Python SignatureOverriddenMethod: Rmv duplicate condition 2021-10-17 18:04:20 +05:30
jorgectf
271e2e4c49 Update .expected 2021-10-16 13:12:33 +02:00
jorgectf
14c50e993b Add django GET.get RFS 2021-10-16 13:10:48 +02:00
jorgectf
45146bc798 Merge branch 'main' into jorgectf/python/headerInjection 2021-10-16 12:46:57 +02:00
jorgectf
bf76d9cd8b Fix django test 2021-10-16 10:45:25 +02:00
jorgectf
2db1ffef1e Merge remote-tracking branch 'origin/main' into jorgectf/python/headerInjection 2021-10-16 10:40:52 +02:00
Edoardo Pirovano
0e01b91c7e Language reference: Fix when trailing commas are allowed 2021-10-16 08:57:26 +01:00
Arthur Baars
e26cf7c354 Merge pull request #369 from github/rc/3.3
Merge 3.3 into main
2021-10-15 23:04:12 +02:00
Ian Lynagh
e485a16993 Java: Don't use dbscheme tables in CloseType.qll 2021-10-15 18:39:42 +01:00
Calum Grant
5861fcf443 Address review comment 2021-10-15 18:07:18 +01:00
Calum Grant
42c5af3cdf Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:03:12 +01:00
Calum Grant
87adcc2e6b Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:03:04 +01:00
Calum Grant
5265ed6b64 Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:02:54 +01:00
Calum Grant
bf5cc212e1 Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:02:40 +01:00
Calum Grant
48077a5757 Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:02:32 +01:00
Calum Grant
86c5b5d944 Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:02:20 +01:00
Calum Grant
579753b0fc Update docs/codeql/codeql-language-guides/codeql-library-for-ruby.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:02:09 +01:00
Calum Grant
2d61519ec6 Update docs/codeql/codeql-language-guides/basic-query-for-ruby-code.rst
Co-authored-by: hubwriter <hubwriter@github.com>
2021-10-15 18:01:56 +01:00
Geoffrey White
f38dade578 C++: Disable the two null termination queries enabled by 6794. 2021-10-15 17:39:12 +01:00
Nick Rolfe
8469a535e3 Merge pull request #366 from github/merge-3.3-main-1
Merge 3.3 into main
2021-10-15 17:18:39 +01:00
Arthur Baars
804aef9b4a Merge remote-tracking branch 'codeql/main' into 'main'
Conflicts:
	config/identical-files.json
2021-10-15 16:37:59 +02:00
Arthur Baars
0e7b1f516c Merge remote-tracking branch 'origin/rc/3.3' into 'main' 2021-10-15 16:36:09 +02:00
Arthur Baars
f296cc7860 Merge pull request #362 from github/merge-3.3-main
Merge 3.3 into main
2021-10-15 16:01:56 +02:00
Erik Krogh Kristensen
fe891746bf C++: fix implicit this 2021-10-15 14:59:48 +01:00
Geoffrey White
a0e501c3a9 Sync identical files. 2021-10-15 14:34:02 +01:00
Erik Krogh Kristensen
caeeebf572 add explicit this qualifier on all of java 2021-10-15 15:27:37 +02:00
Arthur Baars
ceecb23118 Merge remote-tracking branch 'rc/3.3' into 'main' 2021-10-15 15:21:48 +02:00
Tom Hvitved
888a1b38aa C#: Handle Nullable<T> default parameter values in assemblies 2021-10-15 14:23:18 +02:00
Taus
b2e4276bc8 Merge pull request #6886 from aschackmull/java-python/perffix-transitive-step-x3
Java/Python: Fix some potential performance problems due to transitive deltas.
2021-10-15 11:06:35 +02:00
Tom Hvitved
86b1305e35 Merge pull request #6883 from hvitved/csharp/inline-expectations
C#: Adopt inline test expectations framework
2021-10-15 09:33:22 +02:00
Anders Schack-Mulligen
4de1deefc4 Merge pull request #6889 from tausbn/java-fix-import-order
Java: Fix import order in `SignAnalysisSpecific`
2021-10-15 09:17:50 +02:00
Anders Schack-Mulligen
0b82289950 Merge pull request #6828 from zbazztian/adjust-jsp-locations
Adjust locations of results in JSP files
2021-10-15 08:28:11 +02:00
hubwriter
4f247bab4e Add Ruby to language table 2021-10-14 17:13:42 +01:00
Taus
a9c5fd2cc0 Java: Fix import order in SignAnalysisSpecific 2021-10-14 15:51:56 +00:00
Geoffrey White
8f30b8b586 Autoformat. 2021-10-14 16:00:23 +01:00
Anders Schack-Mulligen
eb0a88d39c Merge pull request #6885 from aschackmull/java/perffix-transitve-step
Java: Fix performance problem due to transitive step.
2021-10-14 16:51:51 +02:00
hubwriter
75066813ee Add more Ruby refs as per CD plan 2021-10-14 15:51:28 +01:00
Anders Schack-Mulligen
f6a517c998 Merge pull request #6882 from MathiasVP/fix-unnecessary-exists
C++/Python: Remove unnecessary `exists`
2021-10-14 16:44:05 +02:00
Anders Schack-Mulligen
310eec07c1 Java/Python: Fix some potential performance problems due to transitive deltas. 2021-10-14 16:10:00 +02:00
Anders Schack-Mulligen
cb5f2559ea Java: Fix performance problem due to transitive step. 2021-10-14 15:54:54 +02:00
Geoffrey White
f08d2ee759 Merge branch 'main' into setliterals 2021-10-14 14:39:39 +01:00
Geoffrey White
9d63efe495 Python: Set literals. 2021-10-14 14:22:44 +01:00
Geoffrey White
b9cce57db4 JS: Fix mistake. 2021-10-14 14:22:43 +01:00
Geoffrey White
882adc8e50 JS: Set literals. 2021-10-14 14:22:42 +01:00
Geoffrey White
a82c76d2f9 Java: Set literals. 2021-10-14 14:22:40 +01:00
Geoffrey White
3983587682 C#: Set literals. 2021-10-14 14:22:39 +01:00
Tom Hvitved
083214f85a C#: Use inline test expectations for FieldFlow.ql 2021-10-14 15:22:21 +02:00
Tom Hvitved
ed6a182cd1 C#: Adopt inline test expectations framework 2021-10-14 15:22:21 +02:00
Anders Schack-Mulligen
8b6baa250c Merge pull request #6878 from aschackmull/remove-singleton-setliteral
C++/C#/Java/JavaScript/Python: Remove singleton set literals.
2021-10-14 14:53:05 +02:00
Rasmus Wriedt Larsen
7cd5e681dd Merge pull request #6693 from yoff/python/promote-regex-injection
Python: Promote `py/regex-injection`
2021-10-14 14:49:05 +02:00
Mathias Vorreiter Pedersen
47a85bbb1d Merge pull request #6869 from MathiasVP/fix-prefix/suffix-equality
Java/JS/Python: Replace '.prefix'/'.suffix' with '.matches'
2021-10-14 13:47:03 +01:00
Rasmus Wriedt Larsen
a5ab0b9100 Merge pull request #6871 from tausbn/python-fix-uses-of-implicit-this
Python: Fix uses of "implicit `this`"
2021-10-14 14:38:13 +02:00
Tom Hvitved
3acd718876 Merge pull request #360 from github/bump-codeql
Bump `codeql` submodule
2021-10-14 14:00:57 +02:00
Tom Hvitved
b12561865a Bump codeql submodule 2021-10-14 13:41:48 +02:00
Nick Rolfe
1920cd1c7e Merge pull request #359 from github/explicit_this
Add explicit `this` qualifiers in generated code
2021-10-14 12:40:09 +01:00
Anders Schack-Mulligen
10d6803b05 Merge pull request #6880 from hvitved/csharp/explicit-this
C#: Add explicit `this` qualifiers
2021-10-14 13:31:04 +02:00
Mathias Vorreiter Pedersen
8049d3f738 Python: Remove unnecessary 'exists'. 2021-10-14 12:02:57 +01:00
Mathias Vorreiter Pedersen
69ed7c543f C++: Remove unnecessary 'exists'. 2021-10-14 11:59:59 +01:00
Nick Rolfe
ec91111848 Add explicit this qualifiers in generated code 2021-10-14 11:53:27 +01:00
Tom Hvitved
dde054d5a7 Merge pull request #357 from github/erik-krogh/fix-implicit-this
Add explicit `this` qualifiers
2021-10-14 12:00:58 +02:00
Tom Hvitved
f5420333e2 Sync shared files 2021-10-14 11:49:02 +02:00
Tom Hvitved
3dc09a3cda Revert changes to shared/generated files 2021-10-14 11:42:05 +02:00
Anders Schack-Mulligen
57cb300759 C++/C#/Java/JavaScript/Python: Remove singleton set literals. 2021-10-14 11:34:22 +02:00
Erik Krogh Kristensen
a358a192c4 add explicit this to all calls to class predicates 2021-10-14 10:11:55 +02:00
Erik Krogh Kristensen
cbd55f2299 add explicit this to all calls to class predicates 2021-10-14 10:10:00 +02:00
Mathias Vorreiter Pedersen
a2371370ff Merge pull request #6865 from MathiasVP/fix-if-none
C++/C#/JS/Python: Replace 'if p() then q() else none()' with a conjunction
2021-10-13 19:47:55 +01:00
Mathias Vorreiter Pedersen
4991301f36 JS: Fix incorrect fix. 2021-10-13 19:45:02 +01:00
Tom Hvitved
c14dcfbfe4 Data flow: Sync 2021-10-13 20:13:28 +02:00
CodeQL CI
2b0415e238 Merge pull request #6741 from yoff/python/model-os-path-file-accesses
Approved by RasmusWL
2021-10-13 11:11:41 -07:00
Tom Hvitved
5be7a97a16 Data flow: Avoid unnecessary non-linear recursion via getConfiguration() 2021-10-13 20:10:26 +02:00
Tom Hvitved
ee44e742f6 Data flow: Avoid bad join-order in pathIntoCallable0 2021-10-13 20:09:43 +02:00
Arthur Baars
236643fc43 Merge pull request #356 from github/rc/3.3
Merge rc/3.3 into main
2021-10-13 19:21:36 +02:00
Arthur Baars
240b33f119 Merge pull request #355 from github/aeisenberg/bump-submodule
Bump codeql submodule
2021-10-13 18:50:25 +02:00
Andrew Eisenberg
ef8eff8c29 Bump codeql submodule 2021-10-13 09:30:52 -07:00
Andrew Eisenberg
878203f1d0 Merge pull request #6862 from github/aeisenberg/tutorial
Move tutorial directly into each qlpack
2021-10-13 09:29:37 -07:00
Andrew Eisenberg
0d1632a5d2 Move tutorial directly into each qlpack
Previously, the tutorial was injected during build time. This is much
simpler.
2021-10-13 08:37:04 -07:00
Arthur Baars
5df728dd7d Merge pull request #354 from github/hvitved/identical-files-fix
Remove "DataFlow2" section from `identical-files.json`
2021-10-13 17:20:40 +02:00
Geoffrey White
2e61ae244a C++: Set literals. 2021-10-13 16:12:36 +01:00
Tom Hvitved
6b46aaaefb Remove "DataFlow2" section from identical-files.json 2021-10-13 17:03:48 +02:00
Arthur Baars
893ca5a250 Merge pull request #353 from github/rc/3.3
Merge rc/3.3 into main
2021-10-13 16:33:42 +02:00
Anders Schack-Mulligen
169cc75c88 Merge pull request #6840 from aschackmull/java/misc-perf
Java: Fix some performance issues.
2021-10-13 15:53:49 +02:00
Andrew Eisenberg
01819cdbde Merge pull request #344 from github/aeisenberg/tutorial 2021-10-13 06:48:55 -07:00
Taus
a6115687aa Python: More implicit this 2021-10-13 13:43:37 +00:00
Taus
a9c8163ab3 Python: Fix uses of implicit this
Quoting the style guide:

"14. _Always_ qualify _calls_ to predicates of the same class with
`this`."
2021-10-13 13:43:36 +00:00
Andrew Eisenberg
0e0441743b Move tutorial directly into each qlpack
See also https://github.com/github/codeql/pull/6862
2021-10-13 15:28:17 +02:00
Arthur Baars
aa4d0021a8 Merge pull request #349 from github/aibaars/bump-codeql-main
Bump codeql submodule on main
2021-10-13 15:26:59 +02:00
Philip Ginsbach
a204b7f3e7 Merge pull request #6866 from github/ginsbach/MoreInstanceofExtensions
more instanceof extensions
2021-10-13 14:21:50 +01:00
Jonas Jensen
c215838531 Merge pull request #6867 from nickrolfe/mergeback
Merge rc/3.3 into main
2021-10-13 15:19:18 +02:00
Mathias Vorreiter Pedersen
6ece3c2b46 Merge pull request #6870 from jbj/cp-fixes
C++: Fix potential Cartesian products
2021-10-13 14:15:33 +01:00
Arthur Baars
f4003406cf Apply suggestions from code review
Co-authored-by: Tom Hvitved <hvitved@github.com>
2021-10-13 15:11:04 +02:00
Jonas Jensen
e80c1ad91f C++: Fix resource-not-released-in-destructor CP
By moving a disjunct outside the scope of an `exists(Function f`
variable it doens't use, the code becomes clearer and can be optimized
better.

The CP in the QL code did not lead to a CP at evaluation time since the
optimizer was smart enough to compensate for it:

    376161  ~37597630%     {0} r1 = SCAN functions OUTPUT {}
    1       ~0%            {0} r2 = STREAM DEDUP r1

Before this change, the largest tuple count in `leakedInSameMethod` on
bitcoin/bitcoin was 2M. Now it's 400k.
2021-10-13 14:24:26 +02:00
Mathias Vorreiter Pedersen
a80860cdc6 Python: Replace '.prefix'/'.suffix' with '.matches'. 2021-10-13 13:23:12 +01:00
Mathias Vorreiter Pedersen
f3bb0a676e JS: Replace '.prefix'/'.suffix' with '.matches'. 2021-10-13 13:23:07 +01:00
Mathias Vorreiter Pedersen
d85d009a54 Java: Replace '.prefix'/'.suffix' with '.matches'. 2021-10-13 13:19:06 +01:00
Jonas Jensen
955344e175 C++: Inline a predicate that contains CPs
The `overflows` predicate had quite severe Cartesian products. We didn't
see them in practice because magic saved us, but we can't rely on magic
in the future, so it seems better to inline this predicate.

Tuple counts and speed look good both before and after.
2021-10-13 14:11:47 +02:00
Philip Ginsbach
c9c0c7f24f fix formatting 2021-10-13 13:10:37 +01:00
Arthur Baars
bf3d291a1c Updates after codeql file sync 2021-10-13 13:24:20 +02:00
Arthur Baars
80ac05d5c6 Bump codeql submodule to 'main' 2021-10-13 13:24:08 +02:00
Mathias Vorreiter Pedersen
bdc54bcda7 Python: Replace 'if p() then q() else none()' with a conjunction. 2021-10-13 12:13:55 +01:00
Mathias Vorreiter Pedersen
887849857d JS: Replace 'if p() then q() else none()' with a conjunction. 2021-10-13 12:13:55 +01:00
Mathias Vorreiter Pedersen
7690625114 C#: Replace 'if p() then q() else none()' with a conjunction. 2021-10-13 12:11:50 +01:00
Mathias Vorreiter Pedersen
ba981c525b C++: Replace 'if p() then q() else none()' with a conjunction. 2021-10-13 12:11:42 +01:00
Arthur Baars
6a18aa4e2a Merge pull request #348 from github/rc/3.3
Merge rc/3.3 into main
2021-10-13 13:08:55 +02:00
Philip Ginsbach
6b9ddf1f65 Guard non-extending subtype of G::Guard 2021-10-13 11:44:22 +01:00
Philip Ginsbach
e3e741251f ParameterNode non-extending subtype of ParameterNodeImpl 2021-10-13 11:42:41 +01:00
Philip Ginsbach
aa656f7542 ArgumentNode non-extending subtype of ArgumentNodeImpl 2021-10-13 11:41:40 +01:00
Philip Ginsbach
4a0aac8505 SuppressionScope non-extending subtype of SuppressionComment 2021-10-13 11:40:32 +01:00
Philip Ginsbach
d0ecabad19 DataFlowCall non-extending subtype of Call 2021-10-13 11:39:25 +01:00
Calum Grant
59e4a6ff7b Move file to correct location 2021-10-13 09:23:04 +01:00
Calum Grant
f575139180 Add Ruby to toctree 2021-10-13 09:10:46 +01:00
Anders Schack-Mulligen
d4fd8780e9 Merge pull request #6863 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-10-13 08:58:18 +02:00
Anders Schack-Mulligen
306388a6bc Update java/ql/src/Likely Bugs/Comparison/StringComparison.ql 2021-10-13 08:57:31 +02:00
github-actions[bot]
2f27a0c9f9 Add changed framework coverage reports 2021-10-13 00:09:35 +00:00
Andrew Eisenberg
8285878504 Merge pull request #6861 from github/aeisenberg/qlpack-defaultSuite
QlPacks: Add the defaultSuite to query packs that are missing it
2021-10-12 14:27:09 -07:00
Andrew Eisenberg
7a0437f159 Merge pull request #343 from github/aeisenberg/defaultSuite
Add defaultSuite
2021-10-12 14:26:35 -07:00
Andrew Eisenberg
d9ab13b43d Update ql/src/qlpack.yml
Co-authored-by: Arthur Baars <aibaars@github.com>
2021-10-12 13:01:03 -07:00
Andrew Eisenberg
2fca1f57c6 Add defaultSuite
Also, change the dependencies to be in alignment with other standard qlpacks.
2021-10-12 21:57:53 +02:00
Arthur Baars
4e79d9fad6 Merge pull request #334 from github/RasmusWL/normalize-qlpack
Packaging: Normalize src/qlpack.yml
2021-10-12 21:56:31 +02:00
Andrew Eisenberg
bbb2637bcc QlPacks: Add the defaultSuite to query packs that are missing it
Also, change some examples pack names from `codeql-lang-examples` to
`codeql/lang-examples`. This doesn't affect behaviour since internally,
the legacy name is converted to the modern name.
2021-10-12 11:54:50 -07:00
Arthur Baars
bf139a09f9 Merge pull request #341 from github/rc/3.3
Rc/3.3 mergeback
2021-10-12 20:48:21 +02:00
Arthur Baars
a78ee535a0 Merge pull request #340 from github/mergeback
Merge rc/3.3 into main
2021-10-12 20:16:59 +02:00
Rasmus Lerchedahl Petersen
83490e9a03 Python: update change note 2021-10-12 19:27:27 +02:00
Aditya Sharad
a517a05ca8 Merge pull request #6830 from github/henrymercer/report-extraction-errors-as-warnings
C++: Improve SARIF severity level reporting of extractor diagnostics
2021-10-12 09:59:27 -07:00
Calum Grant
30a00b22c9 CodeQL library for Ruby 2021-10-12 17:33:09 +01:00
Anders Schack-Mulligen
0e5f89a03c Merge pull request #6463 from smowton/smowton/admin/gson-unsafe-deserialization
Java: add Gson support to unsafe-deserialization query
2021-10-12 16:15:27 +02:00
Mathias Vorreiter Pedersen
6853f491f4 Merge pull request #6794 from geoffw0/impropnullfp
C++: Improvements to cpp/improper-null-termination
2021-10-12 14:47:02 +01:00
Tom Hvitved
10739b11ee Merge pull request #6841 from hvitved/dataflow/incorrect-summary-chaining
Data flow: Add tests for missing summary flow
2021-10-12 15:44:21 +02:00
Rasmus Lerchedahl Petersen
6c108e43d9 Python: address review 2021-10-12 15:16:48 +02:00
Rasmus Lerchedahl Petersen
cf92e1eee7 Python: move getStringArgIndex 2021-10-12 15:11:00 +02:00
Chris Smowton
83c6406167 Update javadoc 2021-10-12 13:51:02 +01:00
Tom Hvitved
cc305ed766 Data flow: Sync 2021-10-12 14:37:33 +02:00
Tom Hvitved
296e268339 Apply suggestions from code review
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2021-10-12 14:28:32 +02:00
Erik Krogh Kristensen
7d4266aea7 skip pipes and other special files when determining which files to extract 2021-10-12 14:06:41 +02:00
Chris Smowton
3c96e62be7 Remove duplicate declaration 2021-10-12 12:35:05 +01:00
Chris Smowton
8816aa1431 Improve Android stub fidelity to the point that all relevant tests work
Note these still aren't entirely mechanically generated stubs matching the real Android 9.
2021-10-12 12:35:05 +01:00
Chris Smowton
205b6fe6d7 Fix bad merge on Uri.java 2021-10-12 12:35:05 +01:00
Chris Smowton
5da392ebfe Introduce TaintInheritingContent 2021-10-12 12:35:05 +01:00
Chris Smowton
1afc03b9b5 Remove redundant import 2021-10-12 12:35:05 +01:00
Chris Smowton
9e0b112f05 Remove now-unnecessary models and tests 2021-10-12 12:35:05 +01:00
Chris Smowton
490168fb05 Fix comments 2021-10-12 12:35:05 +01:00
Chris Smowton
1dffbcd0bd Fix tests disrupted by re-modelling and stubbing Android 9:
* Account for changed dataflow graph shape using external flow
* Account for BaseBundle only existing as of Android 5
* Properly implement Parcelable, which we previously got away with due to a partial stub
* Restore an Android 11 function that had been added to the Android 9 Context class (I won't get into enforcing the difference in this PR)
2021-10-12 12:35:05 +01:00
Chris Smowton
81c0e66b1d Add change note and update qhelp 2021-10-12 12:35:05 +01:00
Chris Smowton
fc0b18cf61 Add tests for Android flow steps 2021-10-12 12:35:05 +01:00
Chris Smowton
cd2c9e9ca3 Add Gson support to unsafe deserialization query 2021-10-12 12:35:04 +01:00
Anders Schack-Mulligen
6b4ca31783 Merge pull request #6849 from Marcono1234/marcono1234/improvements
Java: Serialization query improvements
2021-10-12 13:30:45 +02:00
Shati Patel
1c3239972c Merge pull request #6854 from shati-patel/packaging-beta-note
Docs: Update beta note for packaging
2021-10-12 10:33:59 +01:00
Taus
75c4d6a8a0 Merge pull request #6650 from yoff/python-dataflow/init-time
Python: Import time dataflow
2021-10-12 11:31:03 +02:00
Rasmus Lerchedahl Petersen
61008fd3d0 Merge branch 'main' of github.com:github/codeql into python/promote-regex-injection 2021-10-12 11:28:12 +02:00
Rasmus Lerchedahl Petersen
b093aaaf27 Python: switch to type tracking
for tracking compiled regexes
2021-10-12 11:23:27 +02:00
yoff
43f7eede0b Merge pull request #6182 from haby0/python/LogInjection
Python: CWE-117 Log injection
2021-10-12 10:54:45 +02:00
yoff
c007c9460c Merge pull request #6843 from RasmusWL/dataflow-bool-expr
Python: Add data-flow for `x or y` and `x and y`
2021-10-12 10:40:54 +02:00
Rasmus Lerchedahl Petersen
f34d1ee997 Python: Update test expectation following rename 2021-10-12 10:36:18 +02:00
Tom Hvitved
97bbb12e06 Merge pull request #6838 from hvitved/csharp/enumerate-files-dir-not-found
C#: Make `GetCSharpArgsLogs` robust against log directory not existing
2021-10-12 10:00:27 +02:00
haby0
d52f95d24d Auto Formatting 2021-10-12 09:36:44 +08:00
Mathias Vorreiter Pedersen
df8c399efb Merge pull request #6710 from ihsinme/ihsinme-patch-70
CPP: Add query for CWE-1041 Use of Redundant Code
2021-10-11 17:17:01 +01:00
ihsinme
4334acb6f2 Update FindWrapperFunctions.qhelp 2021-10-11 18:40:03 +03:00
Tony Torralba
a8aa8e3bb4 Use InlineExpectationsTest directly 2021-10-11 16:38:20 +02:00
yoff
0629ce00de Merge pull request #6214 from haby0/python/ClientSuppliedIpUsedInSecurityCheck
[Python] CWE-348:  Client supplied ip used in security check
2021-10-11 16:38:04 +02:00
Geoffrey White
ac6acfb660 C++: Use data flow. 2021-10-11 15:36:00 +01:00
Owen Mansel-Chan
058a04f756 Merge pull request #6795 from owen-mc/inline-expectation-test-trivial-change
Change class name in InlineExpectationTest to avoid clash
2021-10-11 15:35:17 +01:00
shati-patel
c7fbddce54 Docs: Update beta note for packaging 2021-10-11 15:02:25 +01:00
Rasmus Wriedt Larsen
bca1cb141c Packaging: Normalize src/qlpack.yml
Port of 4) from https://github.com/github/codeql/pull/6605

> Dependencies from query packs to other packs are always "*" since
these dependencies are always from source and we should get the
latest.

Compare with [C++ change](https://github.com/github/codeql/pull/6605/files#diff-0236560ca1b9c19eb7c74d8bfecd1c78005e762122f8bcdaee9eb9b20460bf9c).
2021-10-11 14:36:14 +02:00
Marcono1234
ba0dbd5871 Java: Improve IncorrectSerializableMethods.ql; address review comments 2021-10-11 14:29:10 +02:00
Rasmus Lerchedahl Petersen
19f6cc00c8 Python: rewrite import time test 2021-10-11 14:28:25 +02:00
yoff
5aee715931 Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-10-11 13:00:21 +02:00
Tom Hvitved
68ea3e7b49 Data flow: Add debugging predicates for rendering data flow graphs for summarized callables 2021-10-11 11:29:08 +02:00
Tom Hvitved
d5955f1ae1 Java: Add test for missing summary flow 2021-10-11 11:29:08 +02:00
Tom Hvitved
30bf2aade4 C#: Add test for missing summary flow 2021-10-11 11:29:08 +02:00
Tom Hvitved
61973c399e C#: Make GetCSharpArgsLogs robust against log directory not existing 2021-10-11 11:28:49 +02:00
Tom Hvitved
c75e2d306d Merge pull request #6852 from hvitved/csharp/interpret-element0-bad-magic
C#: Avoid bad magic in `interpretElement0`
2021-10-11 11:27:35 +02:00
haby0
c2d0fcfbe6 Update python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-10-11 16:46:02 +08:00
haby0
29ddc76e2f Update python/ql/test/experimental/query-tests/Security/CWE-117/LogInjection.expected
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-10-11 16:43:30 +08:00
Rasmus Wriedt Larsen
8444388ec7 Python: Update .expected 2021-10-11 09:48:56 +02:00
Rasmus Wriedt Larsen
1552c108b0 Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-10-11 09:34:15 +02:00
Tom Hvitved
b05d76a131 C#: Avoid bad magic in interpretElement0 2021-10-11 09:30:52 +02:00
Tony Torralba
0919746f1a Merge pull request #6844 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-10-11 09:25:46 +02:00
github-actions[bot]
ea0a0522a7 Add changed framework coverage reports 2021-10-11 00:08:32 +00:00
Marcono1234
a7670fbcab Java: Enhance IncorrectSerializableMethods.ql 2021-10-11 02:05:53 +02:00
Marcono1234
12936ff5fe Java: Fix IncorrectSerializableMethods.ql using wrong readObject signature 2021-10-11 02:05:53 +02:00
Marcono1234
b009886664 Java: Add TypeObjectInputStream 2021-10-11 02:05:50 +02:00
Marcono1234
a74d423d82 Java: Improve AnnotationPresentCheck.ql 2021-10-11 01:03:46 +02:00
Rasmus Lerchedahl Petersen
64b1aeaecd Python: Shorten toString for module vars 2021-10-10 15:59:31 +02:00
Rasmus Lerchedahl Petersen
0aa632d149 Python: Move writing of module vars
into runtime jump steps.
2021-10-10 15:49:33 +02:00
yoff
9c9c5c09ff Merge pull request #6837 from RasmusWL/more-unsafe-deserialization-sinks
Python: More unsafe deserialization sinks
2021-10-10 14:33:53 +02:00
yoff
f6122c8a6c Merge pull request #6734 from erik-krogh/regBehind
JS/PY: do not filter away regular expressions with lookbehinds
2021-10-10 13:54:26 +02:00
Henry Mercer
5b26d41d27 C++: Improve SARIF severity level reporting of extractor diagnostics 2021-10-08 17:53:55 +01:00
Rasmus Wriedt Larsen
a50b193c40 Python: Model data-flow for x or y and x and y 2021-10-08 18:32:30 +02:00
Rasmus Wriedt Larsen
15476c2513 Python: Add data-flow tests for BoolExp
> 6.11. Boolean operations

> The expression x and y first evaluates x; if x is false, its value is
> returned; otherwise, y is evaluated and the resulting value is
> returned.

> The expression x or y first evaluates x; if x is true, its value is
> returned; otherwise, y is evaluated and the resulting value is
> returned.
2021-10-08 18:29:06 +02:00
Geoffrey White
79f13cae55 Merge pull request #6839 from geoffw0/toctoufp
CPP: Add test cases for cpp/toctou-race-condition
2021-10-08 16:15:00 +01:00
Rasmus Lerchedahl Petersen
705970cedd Python: Update tests to use correct tag 2021-10-08 16:57:36 +02:00
Cornelius Riemenschneider
84883d115d Merge pull request #6813 from adityasharad/docs/database-create-bazel
CLI docs: Add example for creating a database using a Bazel build command
2021-10-08 16:56:10 +02:00
Rasmus Lerchedahl Petersen
8ba01abcd6 Merge branch 'python-dataflow/init-time' of github.com:yoff/codeql into python-dataflow/init-time 2021-10-08 16:53:08 +02:00
Anders Schack-Mulligen
2185a654de Java: Fix some performance issues. 2021-10-08 15:53:14 +02:00
Anders Schack-Mulligen
5d0e72755d Merge pull request #6770 from aschackmull/java/stream-model
Java: Add models for java.util.stream.
2021-10-08 15:48:50 +02:00
Geoffrey White
1c56573194 C++: Add tests. 2021-10-08 14:30:27 +01:00
Geoffrey White
dd95131630 C++: Test spacing. 2021-10-08 14:28:42 +01:00
Rasmus Lerchedahl Petersen
4807f50c00 Merge branch 'main' of github.com:github/codeql into python-dataflow/init-time 2021-10-08 14:55:01 +02:00
ihsinme
8c42545d1c Update FindWrapperFunctions.qhelp 2021-10-08 13:10:36 +03:00
Rasmus Wriedt Larsen
fd0c386a4c Python: Add change-note 2021-10-08 12:06:18 +02:00
Rasmus Wriedt Larsen
5e6f042f6e Python: Model pickle.Unpickler 2021-10-08 11:55:54 +02:00
Rasmus Wriedt Larsen
75b06d8a25 Python: Model dill.load 2021-10-08 11:55:54 +02:00
Rasmus Wriedt Larsen
4820be3b10 Python: Model keyword arguments to dill.loads 2021-10-08 11:55:54 +02:00
Rasmus Wriedt Larsen
9180257afe Python: Refactor Dill.qll
So it matches the layout of all our other qll modules modeling a PyPI
package.
2021-10-08 11:55:54 +02:00
Rasmus Wriedt Larsen
f9333fc551 Python: Expand dill tests 2021-10-08 11:55:54 +02:00
Rasmus Wriedt Larsen
42980a1ab4 Python: Model shelve.open 2021-10-08 11:55:54 +02:00
Tony Torralba
2df30dc107 Use InlineFlowTest for local and remote flow tests 2021-10-08 11:48:35 +02:00
Anders Schack-Mulligen
446c738f20 Merge pull request #6790 from aschackmull/dataflow/force-precision
Dataflow: Force high precision of certain Contents.
2021-10-08 11:44:26 +02:00
ihsinme
d79596354e Update cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-10-08 11:50:45 +03:00
Tom Hvitved
951df380a9 Merge pull request #6829 from hvitved/csharp/gvn-to-string-concat-range
C#: Speedup GVN string `concat`s by pulling ranges into separate predicates
2021-10-08 10:02:31 +02:00
Anders Schack-Mulligen
06e59f3b17 Merge pull request #6832 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-10-08 09:53:49 +02:00
Anders Schack-Mulligen
1bec58dee5 Dataflow: Fix more qldoc: s/accesspath/access path/. 2021-10-08 09:41:26 +02:00
github-actions[bot]
062250741a Add changed framework coverage reports 2021-10-08 00:08:55 +00:00
Rasmus Wriedt Larsen
a81d359669 Python: Model marshal.load 2021-10-07 21:27:51 +02:00
Rasmus Wriedt Larsen
1b61296ea5 Python: Model pickle.load 2021-10-07 21:25:48 +02:00
Rasmus Wriedt Larsen
27c368a444 Python: Model keyword arguments to pickle.loads 2021-10-07 21:24:12 +02:00
Rasmus Wriedt Larsen
3592b09d56 Python: Expand stdlib decoding tests
The part about claiming there is decoding of the input to `shelve.open`
is sort of an odd one, since it's not the filename, but the contents of
the file that is decoded.

However, trying to only handle this problem through path injection is
not enough -- if a user is able to upload and access files through
`shelve.open` in a path injection safe manner, that still leads to code
execution.

So right now the best way we have of modeling this is to treat the
filename argument as being deserialized...
2021-10-07 21:11:51 +02:00
Rasmus Wriedt Larsen
a31bf75169 Python: Refactor pickle.loads() modeling 2021-10-07 20:28:30 +02:00
Robert Marsh
2539e3247a Merge pull request #6814 from MathiasVP/fix-qldoc-in-copy-instruction
C++/C#: Fix QLDoc of `CopyInstruction`
2021-10-07 11:18:38 -07:00
Aditya Sharad
2ed572095c CLI docs: Address comments on Bazel example 2021-10-07 10:51:11 -07:00
yoff
933412eb8d Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-10-07 17:45:07 +02:00
Chris Smowton
9a80ab31c4 Merge pull request #6567 from luchua-bc/java/sensitive_android_file_leak
Java: CWE-200 - Query to detect exposure of sensitive information from android file intent
2021-10-07 15:19:39 +01:00
Chris Smowton
39640efc9b Remove no-longer-needed TaintPreservingCallables and update test expectations 2021-10-07 14:33:39 +01:00
Anders Schack-Mulligen
2b88a2aa0c Dataflow: Fix qldoc: s/accesspath/access path/. 2021-10-07 14:46:24 +02:00
Anders Schack-Mulligen
f885751107 Java: Add change note. 2021-10-07 14:42:19 +02:00
Tom Hvitved
764a987b09 C#: Speedup GVN string concats by pulling ranges into separate predicates 2021-10-07 13:51:05 +02:00
haby0
538bf7c321 Update python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-10-07 19:44:25 +08:00
Anders Schack-Mulligen
fc69acee46 Java: Add test. 2021-10-07 13:28:02 +02:00
Chris Smowton
b7448d55ed Introduce TaintInheritingContent instead of using parts of DataFlowPrivate 2021-10-07 11:20:19 +01:00
Henry Mercer
4b069d41f6 Merge pull request #6818 from github/henrymercer/js/add-classify-files-to-library-pack
JS: Move `ClassifyFiles.qll` to library pack
2021-10-07 11:18:20 +01:00
CodeQL CI
a0dd3d9e75 Merge pull request #6815 from asgerf/js/adjust-security-severity-scores
Approved by erik-krogh, esbena
2021-10-07 02:36:19 -07:00
Sebastian Bauersfeld
f651bc3668 Adjust locations of results in JSP files. This is necessary due to known limitations in VSCode which cause locations with zero character indices to be mapped to invalid ranges. This is hopefully a temporary workaround until this problem has been properly addressed. 2021-10-07 12:45:21 +07:00
Dave Bartolomeo
d8d9073bc2 Merge pull request #6826 from github/aeisenberg/add-library 2021-10-06 20:18:39 -04:00
Andrew Eisenberg
e2b1f6ac50 Packaging: Add library flag to upgrades packs
This flag was missing. It should be there. Otherwise, this
pack cannot be built.
2021-10-06 14:29:55 -07:00
Dave Bartolomeo
0452512de2 Merge pull request #6820 from github/aeisenberg/gitignore
Ignore .codeql folder
2021-10-06 12:59:45 -04:00
Chris Smowton
f88c8a64a1 Copyedit 2021-10-06 17:37:21 +01:00
Chris Smowton
b33daa3d3a Update Intent model tests, and fix models where required 2021-10-06 17:09:47 +01:00
Chris Smowton
4be2347a30 Adapt to use the new shared Intent models 2021-10-06 16:15:18 +01:00
Henry Mercer
83cbc86f50 JS: Move ClassifyFiles.qll to library pack
This allows us to use this library in packs that depend on the
`codeql/javascript-all` library pack.
2021-10-06 16:08:06 +01:00
Andrew Eisenberg
c9c45808b4 Merge pull request #6819 from github/aeisenberg/javascript/fix-compile-errors
Fixes compile errors by moving files
2021-10-06 07:59:50 -07:00
Chris Smowton
91d8b3da23 Sort Intent models 2021-10-06 12:30:40 +01:00
Chris Smowton
f24e310ace Update test expectation details 2021-10-06 12:25:23 +01:00
Chris Smowton
ffdfc0549a Update comment 2021-10-06 12:17:49 +01:00
luchua-bc
987bfa6ca7 Update condition check and qldoc 2021-10-06 12:17:49 +01:00
luchua-bc
8c2fddb297 Update the condition check and use DataFlow in the ql file 2021-10-06 12:17:49 +01:00
Chris Smowton
b0e652a3af Remove AsyncTask models 2021-10-06 12:17:49 +01:00
Chris Smowton
9e0cf5a2fd Update test expectations to include subpaths 2021-10-06 12:17:49 +01:00
Chris Smowton
3607d50994 Update remote flow source locations 2021-10-06 12:17:46 +01:00
luchua-bc
02bfa1ca57 Optimize the query 2021-10-06 12:16:04 +01:00
luchua-bc
0621e65827 Query to detect exposure of sensitive information from android file intent 2021-10-06 12:16:04 +01:00
Anders Schack-Mulligen
d0b307ecfb Merge pull request #6103 from atorralba/atorralba/promote-insecure-javamail
Java: Promote Insecure JavaMail SSL Configuration from experimental
2021-10-06 09:24:11 +02:00
Anders Schack-Mulligen
9505846088 Merge pull request #6821 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-10-06 09:06:14 +02:00
github-actions[bot]
33ee947f8d Add changed framework coverage reports 2021-10-06 00:08:24 +00:00
Andrew Eisenberg
57ef989a89 Fixes compile errors by moving files
The two files moved in this commit are referenced from the
javascript/lib qlpack, but they are located in the
javascript/src qlpack. This causes compile errors when running
compile-ish commands for javascript queries. Moving the
files fixes it.
2021-10-05 14:00:02 -07:00
Andrew Eisenberg
0590e2a5fb Ignore .codeql folder 2021-10-05 13:42:36 -07:00
Chris Smowton
5b13232a9d Merge pull request #6739 from joefarebrother/android-intent-extra
Java: Model Android Bundle and Intent extras methods
2021-10-05 15:39:42 +01:00
Anders Schack-Mulligen
9133adac30 Java: Adjust csv validation. 2021-10-05 13:13:28 +02:00
Anders Schack-Mulligen
04892df45a Java: Include stream method overrides. 2021-10-05 13:13:28 +02:00
Anders Schack-Mulligen
af7d633f2f Java: Add Stream::mapMulti* and Stream::toList. 2021-10-05 13:13:28 +02:00
Anders Schack-Mulligen
ef80263106 Java: Add models for java.util.stream. 2021-10-05 13:13:27 +02:00
Anders Schack-Mulligen
5d63a76e25 Merge pull request #6797 from Marcono1234/marcono1234/remove-overwritten-NestedType-isStatic-qldoc
Java: Remove overwritten `NestedType.isStatic()` QLDoc
2021-10-05 13:05:53 +02:00
Joe Farebrother
b956238efa Fill in gen/get methods for tests 2021-10-05 12:01:25 +01:00
haby0
a17b0d4e5c Modify Sanitizer 2021-10-05 17:12:04 +08:00
Mathias Vorreiter Pedersen
b089e6d84e C++/C#: Fix QLDoc of 'CopyInstruction'. 2021-10-05 09:14:20 +01:00
Asger Feldthaus
3a20ca96c4 JS: Update CWE tags and severity score of code injection query
The derived security-severity score of the JS code injection query
was much lower than for other languages (6.1 versus 9.3), possibly due
some differences in CWE tags, such as the inclusion of CWE-079.

We also add the more specific CWE-095 ("eval injection") for consistency
with other languages. It is a child of CWE-094 ("code injection") which
was already tagged.
2021-10-05 10:12:19 +02:00
Asger Feldthaus
c4e8af983a JS: Update score and add CWE-730 to LoopBoundInjection
This is a denial-of-service query, but was missing the CWE-730 tag
("denial of service") and consequently had a lower score than the
other DoS queries.
2021-10-05 10:10:01 +02:00
Asger Feldthaus
682a71176d JS: Make TaintedFormatString have same severity as LogInjection
The CWE number for this query is associated with buffer overflows
from printf/scanf-style functions in C++, which has likely determined
its derived security score.

But in JavaScript, a tainted format string is unlikely to lead to
anything worse than log injection so we're manually update its score
to reflect this.
2021-10-05 10:10:01 +02:00
Asger Feldthaus
83ca4ef6d9 JS: Lower security-severity of queries with speculative threat model
In the CVSS calculator we model this by setting 'Attack Complexity' to
High and 'User Interaction' to Low (as opposed to None).

CVSS vector:
  CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:N/I:H/A:N
2021-10-05 10:10:01 +02:00
Tony Torralba
a86cbd884e Apply suggestions from code review
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2021-10-05 09:40:22 +02:00
Tony Torralba
3323f7ab1a Fix qhelp 2021-10-05 09:18:50 +02:00
Tony Torralba
9f54b1065a Apply suggestions from code review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2021-10-05 09:18:49 +02:00
Tony Torralba
9c1021134a Add some links to qhelp 2021-10-05 09:18:49 +02:00
Tony Torralba
2d1278ece5 Consider setStartTLSRequired for Apache SimpleEmail 2021-10-05 09:18:48 +02:00
Tony Torralba
baffb0ed89 Consider Jakarta Mail 2021-10-05 09:18:47 +02:00
Tony Torralba
a2e9c2f4ab Apply suggestions from code review
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-10-05 09:18:47 +02:00
Tony Torralba
c13bf2a2a1 Add change note 2021-10-05 09:18:46 +02:00
Tony Torralba
73653f77aa Use InlineExpectationsTest 2021-10-05 09:18:45 +02:00
Tony Torralba
8c6d58e6d8 Refactored into libraries 2021-10-05 09:18:44 +02:00
Tony Torralba
0e149f0523 Move from experimental 2021-10-05 09:18:44 +02:00
CodeQL CI
40d98ad678 Merge pull request #6789 from asgerf/js/restrict-package-exports
Approved by erik-krogh
2021-10-05 06:20:23 +01:00
Aditya Sharad
9913221010 CLI docs: Add example for creating a database using a Bazel build command
We have internal material on this subject, so it makes sense to have a reference example.
Bazel builds could be in any compiled language, so follow the pattern
of the generic build script example.
Include the build flags that we recommend to customers,
which turn off Bazel's caching and distributed behaviour
so that CodeQL can observe the entire build.
2021-10-04 11:08:43 -07:00
yoff
f230a37004 Merge pull request #6804 from tausbn/python-fix-bad-magic-in-conditionblock-controls
Python: Fix bad magic in `controls/2`
2021-10-04 19:16:06 +02:00
Geoffrey White
11b8d4191f C++: Repair .expected following merge. 2021-10-04 16:53:33 +01:00
Geoffrey White
2c64fa50d2 Merge branch 'main' into impropnullfp 2021-10-04 16:51:21 +01:00
Mathias Vorreiter Pedersen
7f7f90681f Merge pull request #6808 from MathiasVP/add-cwes-to-incorrect-allocation-handling
C++: Add more CWEs to 'cpp/incorrect-allocation-error-handling'.
2021-10-04 17:02:08 +02:00
Marcono1234
0bce8234d8 Java: Remove overwritten NestedType.isStatic() QLDoc
Did not mention nested non-member interfaces and record classes.
The documentation of the overridden `isStatic()` predicate already mentions
that this predicate holds for explicitly and implicitly static elements, so
overwriting it is not necessary and only adds more maintenance work.
2021-10-04 16:30:57 +02:00
Anders Schack-Mulligen
745ece6e6d Merge pull request #6613 from Marcono1234/marcono1234/literals-test-split
Java: Split literals tests
2021-10-04 16:20:08 +02:00
Mathias Vorreiter Pedersen
eac0222f2c C++: Add more CWEs to 'cpp/incorrect-allocation-error-handling'. 2021-10-04 15:15:40 +01:00
Tom Hvitved
70e41b180e Merge pull request #6800 from hvitved/csharp/constant-cond-tuple-discard
C#: Filter discards in tuples in `ConstantCondition.ql`
2021-10-04 14:38:45 +02:00
Tom Hvitved
9762ce706b Merge pull request #6799 from hvitved/csharp/dead-store-using-discard
C#: Filter using `var _ = ... results` from `DeadStoreOfLocal.ql`
2021-10-04 14:38:15 +02:00
Chris Smowton
041aff6bfd Merge pull request #6802 from atorralba/atorralba/fix-flowtestcasegenerator-folder
Java: Fix flow test case generator's folder name
2021-10-04 13:36:01 +01:00
Nick Rolfe
2a44cd8c98 Merge pull request #6803 from nickrolfe/cpp_upgrade_script
C++: add upgrade script for dbscheme comment changes
2021-10-04 13:31:13 +01:00
Taus
54aec7bb96 Python: Fix bad magic in controls/2
The changes to `ModificationOfParameterWithDefault.ql` and the use of
`ConditionBlock::controls` therein caused the `BasicBlock` argument to
get magicked in, resulting in the following antijoin for the `forall`:

```
[2021-10-04 12:07:46] (108s) Tuple counts for GuardedControlFlow::ConditionBlock::controls_dispred#fbf#antijoin_rhs/5@d84e94 after 1m44s:
201222345 ~7%     {5} r1 = JOIN GuardedControlFlow::ConditionBlock::controls_dispred#fbf#shared#2 WITH Flow::BasicBlock::getASuccessor_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.0 'arg1', Rhs.1 'arg4', Lhs.1 'arg0', Lhs.2 'arg2', Lhs.3 'arg3'
200599933 ~4%     {5} r2 = JOIN r1 WITH Flow::BasicBlock::dominates#ff ON FIRST 2 OUTPUT Lhs.2 'arg0', Lhs.0 'arg1', Lhs.3 'arg2', Lhs.4 'arg3', Lhs.1 'arg4'

0         ~0%     {4} r3 = JOIN GuardedControlFlow::ConditionBlock::controls_dispred#fbf#shared#1 WITH GuardedControlFlow::ConditionBlock#class#f ON FIRST 1 OUTPUT Lhs.0 'arg3', Lhs.2 'arg1', Lhs.1 'arg0', false

0         ~0%     {4} r4 = JOIN GuardedControlFlow::ConditionBlock::controls_dispred#fbf#shared WITH GuardedControlFlow::ConditionBlock#class#f ON FIRST 1 OUTPUT Lhs.0 'arg3', Lhs.2 'arg1', Lhs.1 'arg0', true

0         ~0%     {4} r5 = r3 UNION r4
0         ~0%     {5} r6 = JOIN r5 WITH Flow::BasicBlock::getASuccessor_dispred#ff ON FIRST 2 OUTPUT Lhs.2 'arg0', Lhs.1 'arg1', Lhs.3 'arg2', Lhs.0 'arg3', Rhs.0

200599933 ~4%     {5} r7 = r2 UNION r6
                return r7
```
(cancelled)

I observed that quick-eval'ing the `controls` predicate exhibit no such
bad join order (and terminated quickly) which lead me to conclude that
this was a case of bad magic.

Adding the `pragma[nomagic]` resulted in a return to the previous
performance.
2021-10-04 12:16:53 +00:00
Tony Torralba
064aba810b Remove hyphens from the flow testcase generator folder name
So that it can be imported from the autogenerated query `gen.ql`
2021-10-04 13:31:07 +02:00
Nick Rolfe
5aec84b672 C++: add upgrade script for dbscheme comment changes 2021-10-04 12:30:42 +01:00
Asger Feldthaus
cbd577694c JS: Autoformat 2021-10-04 13:30:15 +02:00
Tom Hvitved
a315640082 C#: Address review comments 2021-10-04 13:15:26 +02:00
Tom Hvitved
f06632a8e7 C#: Filter discards in tuples in ConstantCondition.ql 2021-10-04 13:04:18 +02:00
Rasmus Lerchedahl Petersen
aa91c26792 Python: Add missing taint steps 2021-10-04 12:12:07 +02:00
yoff
4521a9fdf0 Update python/ql/lib/semmle/python/frameworks/Stdlib.qll
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-10-04 11:36:53 +02:00
Anders Schack-Mulligen
65a4f36cf8 Merge pull request #6767 from aschackmull/dataflow/callback-postupdate
Dataflow: Support side-effects for callbacks in summaries.
2021-10-04 11:13:18 +02:00
Tom Hvitved
70b9b002cb C#: Add change note 2021-10-04 10:48:07 +02:00
Tom Hvitved
682a2aae3a C#: Filter using var _ = ... results from DeadStoreOfLocal.ql 2021-10-04 10:45:44 +02:00
Jonas Jensen
ce27acd099 Merge pull request #6793 from MathiasVP/add-return-value-deref-to-model-util
C++: Handle return value dereferences in `ModelUtil.qll`
2021-10-04 09:22:52 +02:00
Marcono1234
fb1385b3e8 Java: Fix formatting of SpuriousJavadocParam.java 2021-10-03 00:13:36 +02:00
Owen Mansel-Chan
938d003e5e Fix example to use space after $ for consistency 2021-10-02 08:11:49 +01:00
Owen Mansel-Chan
25792b2a45 Change class name to avoid clash with Go and Javascript libraries 2021-10-02 08:04:17 +01:00
Mathias Vorreiter Pedersen
cc8b581c06 C++: Accept test changes. 2021-10-01 22:23:17 +02:00
Mathias Vorreiter Pedersen
cca77ed65c Merge branch 'main' into add-return-value-deref-to-model-util 2021-10-01 22:02:06 +02:00
Geoffrey White
b9a1a451a9 C++: Autoformat. 2021-10-01 19:21:30 +01:00
Tamás Vajk
62aa7b75bd Merge pull request #6792 from tamasvajk/fix/csv-workflow
Let 'ql/lib' folders trigger the CSV workflow
2021-10-01 19:44:48 +02:00
Mathias Vorreiter Pedersen
0679142607 C++: Accept test changes. 2021-10-01 18:27:55 +02:00
Mathias Vorreiter Pedersen
3463c28e24 C++: Add return value dereference to 'callOutput'. This will need to be modified once we get return value side effects in the IR. 2021-10-01 18:27:46 +02:00
Marcono1234
e3fed55945 Java: Add tests for text blocks 2021-10-01 18:16:11 +02:00
Joe Farebrother
085701c7db Remove models.csv 2021-10-01 17:11:12 +01:00
Geoffrey White
51188aa93f C++: Give the two queries medium precision (for now). 2021-10-01 17:04:22 +01:00
Joe Farebrother
5e4498a53a Add more models; fix tests 2021-10-01 16:53:53 +01:00
Geoffrey White
a62772c274 C++: Add change note. 2021-10-01 16:35:12 +01:00
Marcono1234
924b7320bc Java: Add test for NullLiteral 2021-10-01 17:27:54 +02:00
Marcono1234
bb6e6f4808 Java: Split literals tests
This allows changing individual tests in the future without having to adjust
the expected output of all other tests.
2021-10-01 17:27:50 +02:00
Geoffrey White
ada30800c9 C++: Exclude results where identity-like functions obscure operations on a variable. 2021-10-01 16:16:06 +01:00
Anders Schack-Mulligen
99ba80d492 C#: Adjust test output. 2021-10-01 16:57:30 +02:00
Tamas Vajk
ebe0988d9a Let 'ql/lib' folders trigger the CSV workflow 2021-10-01 16:30:56 +02:00
Geoffrey White
11d7a0b712 C++: Exclude results where the address of the variable is taken. 2021-10-01 14:39:02 +01:00
Geoffrey White
d41e517757 C++: Simplify mayAddNullTerminator. 2021-10-01 14:15:05 +01:00
Geoffrey White
ec2e4f432a C++: Add more test cases, inspired by FPs on LGTM with the query. 2021-10-01 14:03:41 +01:00
Geoffrey White
74957dcb2e C++: Test spacing. 2021-10-01 13:59:34 +01:00
Anders Schack-Mulligen
6359c44622 Java: Autoformat. 2021-10-01 14:05:47 +02:00
yoff
1ce9426adf Merge pull request #6761 from RasmusWL/cryptodome-sha3
Python/JS: Recognize SHA-3 hash functions
2021-10-01 13:33:36 +02:00
Anders Schack-Mulligen
98f68cb053 Dataflow: Sync. 2021-10-01 13:11:43 +02:00
Anders Schack-Mulligen
490df2027b Dataflow: Add language-specific predicate forceHighPrecision(). 2021-10-01 13:11:14 +02:00
Anders Schack-Mulligen
d4f1a9602f Dataflow: Force high precision of certain Contents. 2021-10-01 13:03:50 +02:00
Anders Schack-Mulligen
eb26b4a04b Merge pull request #6755 from alexet/alexet/cache-params-string
Java: Fix more performance issues with future versions of codeql.
2021-10-01 12:54:53 +02:00
Asger Feldthaus
c8e7df7900 JS: Add test case 2021-10-01 12:02:40 +02:00
Asger Feldthaus
600e5bad0d JS: Exclude methods declared private/protected 2021-10-01 11:46:32 +02:00
Asger Feldthaus
af1b04de9c JS: Restrict what property names that are considered public exports 2021-10-01 11:42:03 +02:00
Mathias Vorreiter Pedersen
a3cf721b9e Merge pull request #6713 from geoffw0/cwe139
C++: New query for 'Cleartext transmission of sensitive information'
2021-10-01 11:10:36 +02:00
Geoffrey White
679b0f9b73 C++: Autoformat. 2021-10-01 09:40:16 +01:00
Rasmus Lerchedahl Petersen
175a06fe73 Python: Fix compile error due to predicate rename 2021-10-01 10:33:42 +02:00
Anders Schack-Mulligen
799e099d1d Merge pull request #6784 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-10-01 10:05:34 +02:00
github-actions[bot]
3d61c81456 Add changed framework coverage reports 2021-10-01 00:09:22 +00:00
Chris Smowton
f48c418d6d Merge pull request #5907 from x-f1v3/java/hardcoded-shiro-key
Java: CWE-798: Query to detect hard-coded SHIRO key
2021-09-30 17:58:12 +01:00
Chris Smowton
ec4cb7c90f Fix typo 2021-09-30 16:22:12 +01:00
Chris Smowton
cb4ce36d3c Update change note; drop unnecessary import 2021-09-30 15:00:13 +01:00
Chris Smowton
b0983cb726 Specifically include Base64 encode/decode as a likely intermediate step for hardcoded credentials 2021-09-30 14:57:49 +01:00
Chris Smowton
b57a58c253 Amend change note 2021-09-30 14:27:05 +01:00
f1v3
24c9bb2fb7 autoformat 2021-09-30 14:26:19 +01:00
f1v3
168fc4170d Apply suggestions from code review 2021-09-30 14:26:14 +01:00
f1v3
f3bde56de9 detects a hard-coded cipher key for shiro 2021-09-30 14:22:48 +01:00
Chris Smowton
60a023d064 Merge pull request #5852 from luchua-bc/java/hardcoded-azure-credential
Java: CWE-798 Query to detect hard-coded Azure credentials
2021-09-30 14:11:29 +01:00
Rasmus Lerchedahl Petersen
35d9005eae Python: typo again.. 2021-09-30 14:39:44 +02:00
Rasmus Lerchedahl Petersen
f3fc56a167 Python: typos 2021-09-30 14:39:05 +02:00
Rasmus Lerchedahl Petersen
d19d37bf9b Python: more suggestions from review 2021-09-30 14:36:26 +02:00
yoff
c1c63d0c28 Merge pull request #6738 from RasmusWL/qldoc-getArgByName
Python: Add QLDoc to `Function.getArgByName`
2021-09-30 14:11:18 +02:00
yoff
46e62cd963 Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-09-30 14:00:18 +02:00
Rasmus Lerchedahl Petersen
02e91b3902 Python: Model functions that will raise
on non-existing files.
2021-09-30 13:36:24 +02:00
Jonas Jensen
45cf6344cd Merge pull request #6184 from github/rdmarsh2/improve-exec-tainted
C++: Refactor ExecTainted.ql to only report results after string concatenation
2021-09-29 19:21:13 +02:00
CodeQL CI
e9b4e571e1 Merge pull request #6775 from RasmusWL/fix-hasLocationInfo-url
Approved by aschackmull, erik-krogh, hvitved, jbj, tausbn
2021-09-29 16:51:08 +01:00
alexet
447eb23356 Java: Fix for tc magic issue with subtyping. 2021-09-29 16:01:08 +01:00
Joe Farebrother
3ae5f13c3d Generate tests and stubs 2021-09-29 15:44:21 +01:00
Tamás Vajk
089bb33113 Merge pull request #6773 from tamasvajk/fix/global-stmt-library
C#: Handle invalid code gracefully: global statements in library
2021-09-29 16:18:05 +02:00
Rasmus Wriedt Larsen
ba990f72f2 Another hasLocationInfo URL reference fix 2021-09-29 14:00:28 +02:00
Rasmus Wriedt Larsen
987b573709 Fix hasLocationInfo URL reference
Follow up to https://github.com/github/codeql/pull/5830
2021-09-29 13:47:58 +02:00
alexet
dea8dde566 Java: Improve performance of confusing overloading query. 2021-09-29 12:17:30 +01:00
Tamas Vajk
e17071723f C#: Handle invalid code gracefully: global statements in library 2021-09-29 10:23:33 +02:00
Mathias Vorreiter Pedersen
8dcf7926de Merge pull request #6760 from andersfugmann/relax_memberMayBeVarSize
Increase precision to high for cpp/static-buffer-overflow
2021-09-29 10:09:11 +02:00
Benjamin Muskalla
d09c3bf863 Merge pull request #6748 from bmuskalla/fixHiddenTypesTestGenerator
Java: Avoid stubbing methods with private parameter types
2021-09-29 09:27:13 +02:00
Anders Schack-Mulligen
1a92fa5d92 Merge pull request #6772 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-09-29 09:25:19 +02:00
github-actions[bot]
8d2ad4ed17 Add changed framework coverage reports 2021-09-29 00:08:05 +00:00
Calum Grant
5317022d2e Basic query for Ruby 2021-09-28 20:51:21 +01:00
Geoffrey White
89098f54be C++: Correct comment. 2021-09-28 20:03:42 +01:00
Benjamin Muskalla
5f659f6e48 Merge branch 'main' into fixHiddenTypesTestGenerator 2021-09-28 17:42:39 +02:00
Geoffrey White
10323ac819 Update cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 15:13:29 +01:00
Shati Patel
ee46717c76 Merge pull request #6771 from shati-patel/mergeback-3.2-main
Merge 3.2 into main
2021-09-28 14:52:17 +01:00
Jonas Jensen
914e621d1b Merge pull request #6678 from andersfugmann/refactor_use_of_isGuardPhi
C++: Refactor code to use predicate isGuardPhi/4
2021-09-28 15:45:05 +02:00
Shati Patel
976190e84d Merge pull request #6764 from shati-patel/slides-links
Docs: Fix a few links in the training slides
2021-09-28 14:35:46 +01:00
Mathias Vorreiter Pedersen
06eb93da3f Merge pull request #6769 from github/docfix-dead-links-in-readme
Fix dead links in README.md
2021-09-28 15:21:19 +02:00
Mathias Vorreiter Pedersen
7197f41e75 Fix dead links in README.md 2021-09-28 15:12:36 +02:00
Edoardo Pirovano
5488872044 Merge pull request #6505 from edoardopirovano/trailing-comma
QL Language Spec: Trailing comma in set literal
2021-09-28 13:45:09 +01:00
Chris Smowton
413ac4e8f4 Merge pull request #6684 from owen-mc/java/model/apache-collections-subpackages
Java: model remaining subpackages of Apache Commons Collections
2021-09-28 12:28:48 +01:00
Anders Schack-Mulligen
e95dc82087 Autoformat. 2021-09-28 13:00:50 +02:00
Tony Torralba
cec6cd0830 Merge pull request #6724 from atorralba/atorralba/android-contentprovider-sources
Java: Add sources for content providers in Android
2021-09-28 12:13:54 +02:00
Chris Smowton
39a12a8464 Remove models that are no longer required 2021-09-28 10:48:43 +01:00
Anders Schack-Mulligen
b11cb88a9f Dataflow: Sync to C#. 2021-09-28 11:45:33 +02:00
Anders Schack-Mulligen
9a9bbe3123 Dataflow: Support side-effects for callbacks in summaries. 2021-09-28 11:42:38 +02:00
Tony Torralba
46eb27cd01 Don't restrict inputs to be ParameterNodes
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2021-09-28 11:21:56 +02:00
Anders Fugmann
ba98c0c1cb Merge remote-tracking branch 'upstream/main' into relax_memberMayBeVarSize 2021-09-28 11:15:11 +02:00
Anders Schack-Mulligen
fc8b439263 Merge pull request #6740 from aschackmull/java/callback-dispatch
Java: Add callback dispatch to more anonymous classes.
2021-09-28 10:49:27 +02:00
Anders Peter Fugmann
a358ea8667 C++: Apply documentation change suggestion
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 10:38:02 +02:00
Anders Schack-Mulligen
c294b75f6c Merge pull request #6766 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-09-28 10:35:43 +02:00
Shati Patel
d5e17f9ebf Merge pull request #6765 from shati-patel/docs-config-fixes
Docs: Fix inconsistencies in sphinx config files
2021-09-28 09:18:02 +01:00
Anders Peter Fugmann
c7ea7ca5cd C++: Apply documentation change suggestion
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 09:40:25 +02:00
Anders Peter Fugmann
49c656d904 C++: Apply documentation change suggestion
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 09:40:07 +02:00
Anders Fugmann
79549c2285 Merge remote-tracking branch 'upstream/main' into refactor_use_of_isGuardPhi 2021-09-28 09:38:16 +02:00
Owen Mansel-Chan
787f36f056 Add a change note 2021-09-28 07:32:28 +01:00
Robert Marsh
d47c4732e2 C++: Update change note date 2021-09-27 17:36:14 -07:00
github-actions[bot]
b7b229d59b Add changed framework coverage reports 2021-09-28 00:08:59 +00:00
Robert Marsh
dfb27d170c C++ fix test compilation errors 2021-09-27 13:58:54 -07:00
shati-patel
64fcbe05c3 Docs: Fix inconsistencies in sphinx config files 2021-09-27 18:54:23 +01:00
shati-patel
31c34870ef Fix warning about "Anonymous hyperlink mismatch" 2021-09-27 18:27:57 +01:00
shati-patel
3c17ac424d Docs: Fix some broken/redirected links 2021-09-27 18:27:30 +01:00
Felicity Chapman
bb6c079e5a Merge pull request #6762 from github/felicitymay-patch-1
Update links to match those on the staging site
2021-09-27 16:49:58 +01:00
Felicity Chapman
a3c1975a84 Update links to match those on the staging site 2021-09-27 16:35:22 +01:00
Owen Mansel-Chan
bdd78d2bc7 Fix stub 2021-09-27 16:24:41 +01:00
Owen Mansel-Chan
29db42c3cd Generate stubs 2021-09-27 16:24:40 +01:00
Owen Mansel-Chan
e6df8164cf Fix up old tests for new helper functions 2021-09-27 16:24:39 +01:00
Owen Mansel-Chan
cf03bd8bd1 Merge new and old tests
# Conflicts:
#	java/ql/test/library-tests/frameworks/apache-collections/TestNew.java
2021-09-27 16:24:38 +01:00
Owen Mansel-Chan
342c14887b Fix existing models for MapUtils 2021-09-27 16:24:37 +01:00
Owen Mansel-Chan
e1101e582e Minor improvement to existing tests 2021-09-27 16:24:37 +01:00
Owen Mansel-Chan
768203bd36 Remove redundant casts 2021-09-27 16:24:36 +01:00
Owen Mansel-Chan
c51fb00082 Add tests for non-public abstract classes 2021-09-27 16:24:35 +01:00
Owen Mansel-Chan
0a92b04c8b Fix up automatically generated tests 2021-09-27 16:24:34 +01:00
Owen Mansel-Chan
15161d8867 Make concrete subclasses of abstract classes 2021-09-27 16:24:33 +01:00
Owen Mansel-Chan
53ee465726 Fix errors in generated tests that stop compilation 2021-09-27 16:24:32 +01:00
Owen Mansel-Chan
a20acfee25 Add automatically generated tests
Also update test.ql to use the new InlineFlowTest.
2021-09-27 16:24:31 +01:00
Owen Mansel-Chan
f69787afd0 Miscellaneous model fixes 2021-09-27 16:24:30 +01:00
Owen Mansel-Chan
9b12980688 Do not model some protected methods 2021-09-27 16:24:29 +01:00
Owen Mansel-Chan
cb0f82c36e Do not modelled protected static inner classes 2021-09-27 16:24:29 +01:00
Owen Mansel-Chan
3b678bfbc5 Address review comments 2021-09-27 16:24:28 +01:00
Owen Mansel-Chan
e1750adc38 Address problems highlighted by generating tests 2021-09-27 16:24:27 +01:00
Owen Mansel-Chan
fd0fb9483e Model the remaining subpackages in Apache Commons Collections 2021-09-27 16:24:26 +01:00
Owen Mansel-Chan
3d1d491e6b Model java.lang.Object.clone() better for access paths.
Model value flow for Element, MapKey and MapValue. This assumes
that clone() is a shallow copy.
2021-09-27 16:24:25 +01:00
Edoardo Pirovano
18020707b8 QL Language Spec: Trailing comma in set literal 2021-09-27 15:57:39 +01:00
Anders Schack-Mulligen
cfa0d46b73 Merge pull request #6097 from atorralba/atorralba/promote-xslt-injection
Java: Promote XSLT Injection from experimental
2021-09-27 13:14:57 +02:00
Anders Schack-Mulligen
e027d514f1 Merge pull request #6037 from atorralba/atorralba/promote-spel-injection
Java: Promote SpEL Injection query from experimental
2021-09-27 13:13:35 +02:00
Tony Torralba
d5f675c2dc Fix unbound field
Add tests for non-exported providers
2021-09-27 12:58:28 +02:00
Rasmus Wriedt Larsen
ded3088529 Python/JS: Recognize SHA-3 hash functions
Official names are SHA3-224, SHA3-256, SHA3-384, SHA3-512 as per
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
2021-09-27 12:08:40 +02:00
Tony Torralba
78c12dc505 Move to lib 2021-09-27 12:04:14 +02:00
Tony Torralba
ad08ccb50b Apply suggestion from code review 2021-09-27 12:00:21 +02:00
mc
95751fcc21 Update XsltInjection.qhelp
Made a few minor tweaks during editorial review
2021-09-27 12:00:21 +02:00
Tony Torralba
13417dbf14 Remove DataFlow references from XsltInjection.qll 2021-09-27 12:00:20 +02:00
Tony Torralba
ff21662b23 Refactor XsltInjection.qll 2021-09-27 12:00:18 +02:00
Tony Torralba
6967b06dee Decouple XsltInjection.qll to reuse the taint tracking configuration 2021-09-27 11:59:51 +02:00
Tony Torralba
fc58ada92e Add change note 2021-09-27 11:58:20 +02:00
Tony Torralba
108118afa3 Use InlineExpectationsTest 2021-09-27 11:58:18 +02:00
Tony Torralba
d8bb5273e7 Refactor to use CSV sink models 2021-09-27 11:57:58 +02:00
Tony Torralba
c792567904 Move from experimental 2021-09-27 11:57:53 +02:00
Tony Torralba
6d9a88d1c8 Move to lib 2021-09-27 11:43:46 +02:00
mc
3520fed752 Update SpelInjection.qhelp 2021-09-27 11:40:51 +02:00
Tony Torralba
d10dbbdd9d Apply suggestions from code review
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-09-27 11:40:51 +02:00
Tony Torralba
6bf1e87bbe Remove CSV sinks; make imports private 2021-09-27 11:40:47 +02:00
Tony Torralba
91f46624b6 Refactor SpelInjection.qll 2021-09-27 11:40:26 +02:00
Tony Torralba
94f32d2985 Decouple SpelInjection.qll to reuse the taint tracking configuration 2021-09-27 11:39:30 +02:00
Tony Torralba
569426b04e Consider subtypes of Expression and ExpressionParser
Add parseRaw as additional taint step
2021-09-27 11:38:12 +02:00
Tony Torralba
b0852f6c16 Add change note 2021-09-27 11:37:46 +02:00
Tony Torralba
b985ddb868 Use InlineExpectationsTest 2021-09-27 11:37:41 +02:00
Tony Torralba
079769ed2e Refactored SpelInjection.qll to use CSV sink models 2021-09-27 11:36:56 +02:00
Tony Torralba
fc6af0476f Moved from experimental 2021-09-27 11:36:48 +02:00
Anders Fugmann
03bd7d7f96 C++: Update test results from OverflowStatic 2021-09-27 11:23:08 +02:00
Anders Schack-Mulligen
92ffd8c465 Merge pull request #6749 from aschackmull/java/istextblock
Java: Add StringLiteral.isTextBlock().
2021-09-27 10:54:31 +02:00
Jonas Jensen
b0836a620c Merge pull request #6757 from geoffw0/impropnulltest2
C++: Small improvement to cpp/improper-null-termination
2021-09-27 10:52:49 +02:00
James Fletcher
c977cfe40a Merge pull request #6754 from github/update-link
Update one more link in the QL training content
2021-09-27 08:33:42 +01:00
Anders Fugmann
e0921ac983 C++: Increase precision of cpp/static-buffer-overflow to high 2021-09-27 09:06:36 +02:00
Geoffrey White
7e7dfe2cc4 C++: Understand format arguments. 2021-09-24 19:25:43 +01:00
Geoffrey White
91a8b9fdd9 C++: Add suggested test (and a good variant). 2021-09-24 18:34:28 +01:00
james
1adc5c2a5b update links correctly 2021-09-24 17:00:59 +01:00
Geoffrey White
6901d9d9c2 C++: Add and use getRemoteSocket predicates. 2021-09-24 15:16:48 +01:00
Geoffrey White
9f59bc8f7b C++: Naive translation to use RemoteFlow*Function. 2021-09-24 15:12:14 +01:00
james
e664711f47 make links to slide decks relative 2021-09-24 14:56:48 +01:00
james
23e4ad1abb update one more link 2021-09-24 14:46:14 +01:00
alexet
49f8f46354 Java: Cache params string computation. 2021-09-24 14:12:26 +01:00
Anders Schack-Mulligen
854f2a046a Java: Add StringLiteral.isTextBlock(). 2021-09-24 13:11:18 +02:00
Benjamin Muskalla
70e1724463 Exclude methods with non-public parameter types 2021-09-24 12:41:12 +02:00
Anders Fugmann
cbdabe35de C++: Update test results to reflect changes 2021-09-24 12:29:28 +02:00
Anders Fugmann
032ac50034 C++: Do not warn on static buffer overflow using loop counters, if the loop counter has been widened 2021-09-24 08:31:36 +02:00
Anders Fugmann
3e5f7d0db5 C++: using buildin offsetof for an array member indexed after end is legal 2021-09-24 08:31:35 +02:00
Anders Fugmann
b08eabec68 C++: Relax predicate memberMayBeVarSize to mark all members of size 0 or 1 as variable sized 2021-09-24 08:31:35 +02:00
Anders Fugmann
a4a9e2aa96 C++: Weaken wording on overflow static alert text 2021-09-24 08:31:35 +02:00
haby0
9b969e15fc Modify according to @yoff suggestion 2021-09-24 12:56:10 +08:00
Rasmus Lerchedahl Petersen
f2fbeed490 Python: Model os.path-functions 2021-09-23 15:30:00 +02:00
Rasmus Lerchedahl Petersen
81adb7dd2a Python: Add tests for os.path-functions 2021-09-23 15:28:05 +02:00
Anders Schack-Mulligen
4841c3037d Java: Add callback dispatch to more anonymous classes. 2021-09-23 14:34:56 +02:00
Joe Farebrother
0919042692 Model Bundle and Intent extra methods 2021-09-23 12:03:45 +01:00
ihsinme
13741ba137 Update FindWrapperFunctions.ql 2021-09-23 12:55:03 +03:00
ihsinme
18de9f0aa3 Update FindWrapperFunctions.expected 2021-09-23 12:53:16 +03:00
Rasmus Wriedt Larsen
d4564d5dd1 Python: Add QLDoc to Function.getArgByName 2021-09-23 10:01:04 +02:00
Robert Marsh
49f8fd2164 C++: whitespace fix 2021-09-22 16:54:03 -07:00
Robert Marsh
0c5d642489 C++: Rename SystemFunction and restore QLDoc 2021-09-22 14:22:57 -07:00
Robert Marsh
6f03c3e252 C++: Accept command injection test changes
Making the DefaultTaintTracking configurations inactive removed many
unneeded nodes and edges from the PathGraph predicates.
2021-09-22 14:19:23 -07:00
Robert Marsh
8faeab18b9 C++: move ResolveCall.qll out of internal directory 2021-09-22 11:54:47 -07:00
Robert Marsh
21ed5c430d Merge branch 'main' into rdmarsh2/improve-exec-tainted
Manual fix for conflict in Models.qll
2021-09-22 11:51:18 -07:00
Erik Krogh Kristensen
805d1d170c do not filter away regular expressions with lookbehinds 2021-09-22 17:14:29 +02:00
haby0
6c07a3e260 Apply @yoff's suggestion 2021-09-22 18:50:58 +08:00
Robert Marsh
d6fd83dd6c C++: move resolveCall to its own file for perf
This avoids a performance issue in DataFlowImpl::localFlowStep when the
DataFlow::Configuration subclasses in DefaultTaintTracking are active
in the same query as other Configuration
subclasses.
ResolveCall.qll is kept internal for the moment.
2021-09-21 16:32:09 -07:00
ihsinme
88a257fcdc Apply suggestions from code review
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-09-21 20:32:08 +03:00
Tony Torralba
99881db8bd Add stubs 2021-09-21 12:10:05 +02:00
Tony Torralba
0c1f3ed0b3 Add tests for ContentProvider sources 2021-09-21 12:09:47 +02:00
Tony Torralba
a811ab3aff Add ContentProvider sources 2021-09-21 12:09:28 +02:00
Robert Marsh
a9add04ee3 C++: remove unneed import 2021-09-17 12:17:06 -07:00
Robert Marsh
d3d708bc68 C++: QLDoc for CommandExecution model 2021-09-17 12:16:20 -07:00
Geoffrey White
e7c82d7370 C++: Accept subpaths in tests. 2021-09-17 16:14:24 +01:00
Geoffrey White
24668b2281 Merge branch 'main' into cwe139 2021-09-17 16:04:51 +01:00
Geoffrey White
51243454c8 C++: Change note. 2021-09-17 15:10:55 +01:00
Geoffrey White
90bc138049 CPP: Fix QLDoc comments. 2021-09-17 14:12:04 +01:00
haby0
99167539fb Modify sinks 2021-09-17 17:29:40 +08:00
Geoffrey White
a3de94e868 C++: Assign precision and severity; medium for now, since there are FPs in SAMATE Juliet. 2021-09-17 10:05:06 +01:00
Felicity Chapman
7383988988 Merge pull request #6701 from github/docs-4908-training-note-links
Update links in training notes to use CodeQL microsite
2021-09-17 09:00:36 +01:00
james
e906ded0d1 remove java class 2021-09-17 08:48:26 +01:00
ihsinme
b6bcf9fa44 Add files via upload 2021-09-16 19:18:19 +03:00
ihsinme
b393c6a285 Add files via upload 2021-09-16 19:16:54 +03:00
james
c36292bfd0 a few more links 2021-09-16 17:03:29 +01:00
Rasmus Lerchedahl Petersen
64685f31dc Python: Add missing qldoc
Also do some general cleanup
How was this allowed comitted in the first place?
2021-09-16 16:51:43 +02:00
haby0
0277601705 Eliminate false positives caused by . 2021-09-16 20:59:34 +08:00
Rasmus Lerchedahl Petersen
72bf390ec5 Merge branch 'main' of github.com:github/codeql into python/promote-regex-injection 2021-09-16 14:50:17 +02:00
Robert Marsh
c85cc1455b C++: accept changes to new ExecTainted test 2021-09-15 11:27:13 -07:00
Robert Marsh
a3e1f54e33 C++: Refactor models to prevent IR reevaluation 2021-09-15 10:55:56 -07:00
Robert Marsh
509a3493b6 C++: support new subpaths predicate in ExecTainted 2021-09-15 10:55:56 -07:00
Robert Marsh
09ef8f639e C++: Improve performance by restricting isSource 2021-09-15 10:55:55 -07:00
Robert Marsh
83cc098412 C++: accept test output 2021-09-15 10:55:55 -07:00
Robert Marsh
3cd08bc724 C++: autoformat Printf.qll 2021-09-15 10:55:55 -07:00
Robert Marsh
fe1f9878ba C++: add GVN import to fix reevaluation 2021-09-15 10:55:54 -07:00
Robert Marsh
e874fbbea2 C++: Add path stitching in ExecTainted.ql 2021-09-15 10:55:54 -07:00
Robert Marsh
5dc6e13ab5 C++: use TaintTracking2 in ExecTainted.ql 2021-09-15 10:55:53 -07:00
Robert Marsh
4d2036fa26 C++: change note for cpp/command-line-injection 2021-09-15 10:55:53 -07:00
Robert Marsh
c30e7ec41a C++: raise precision of cpp/command-line-injection 2021-09-15 10:55:53 -07:00
Robert Marsh
181eb803e1 C++: Add QLDoc for getOutputArgument 2021-09-15 10:55:52 -07:00
Robert Marsh
37c92178a5 C++: exclude int/string conversion in ExecTainted 2021-09-15 10:55:52 -07:00
Robert Marsh
5e265f45e1 C++: ExecTainted tests for int/string conversions 2021-09-15 10:55:51 -07:00
Robert Marsh
9926892c8a C++: remove debugging predicates 2021-09-15 10:55:51 -07:00
Robert Marsh
9c478c502e C++: add some more tests for ExecTainted 2021-09-15 10:55:50 -07:00
Robert Marsh
562c8b97ad C++: add comment explaining concatenation logic 2021-09-15 10:55:50 -07:00
Robert Marsh
6f408f949c C++: Refactor ExecTainted.ql to need concatenation
This makes ExecTainted report results only when the tainted value does
not become the start of the string which is eventually run as a shell
command. The theory is that those cases are likely to be deliberate, and
part of the expected threat model of the program (e.g. $CC in make).
This lines up better with the results I considered fixable true
positives in LGTM testing
2021-09-15 10:55:49 -07:00
Robert Marsh
8f4df8603a C++: more tests for command injection 2021-09-15 10:55:49 -07:00
Felicity Chapman
05d83e487d Update all links to CodeQL microsite 2021-09-15 17:08:55 +01:00
haby0
c60eded2de Fix conflicting 2021-09-15 11:07:43 +08:00
haby0
9e63aa9d84 Update query 2021-09-14 21:12:49 +08:00
Rasmus Lerchedahl Petersen
c2d2037726 Python: Add change note and set precision 2021-09-14 13:45:51 +02:00
Rasmus Lerchedahl Petersen
1c7982b319 Python: Move query tests over 2021-09-14 13:29:21 +02:00
Rasmus Lerchedahl Petersen
36e27f2aa4 Python: Remove promoted code:
- queries (`py/regex-injection`)
- concepts (RegexExecution, RegexEscape)
- library models (Stdlib::Re)
2021-09-14 13:14:16 +02:00
Rasmus Lerchedahl Petersen
abbd1d1dc5 Python: Fix errors introduced during port
testing on a database helps..
2021-09-14 13:08:21 +02:00
Rasmus Lerchedahl Petersen
6c82daef3d Python: Move Regexinjection out of experimental
and fix up structure
2021-09-14 11:54:59 +02:00
Rasmus Lerchedahl Petersen
3d5192d6d3 Python: Fix typos 2021-09-14 11:54:11 +02:00
Rasmus Lerchedahl Petersen
a30f697537 Python: Add getName to RegexExecution concept 2021-09-14 11:53:40 +02:00
Anders Fugmann
3f5ab60fb4 C++: Add DEPRECATED to documentation block 2021-09-14 09:55:19 +02:00
Rasmus Lerchedahl Petersen
8f152a5bfb Python: Port regex concepts and adapt PolyRedos 2021-09-13 16:50:00 +02:00
Geoffrey White
67c6b35845 C++: We get many more real world results using taint tracking. 2021-09-13 15:03:28 +01:00
Geoffrey White
0e8064dbf9 C++: Add a test demonstrating taint. 2021-09-13 15:00:31 +01:00
Anders Fugmann
8e9ac18026 C++: Deprecate RangeSSA::isGuardPhi/3 2021-09-13 15:35:05 +02:00
Geoffrey White
ee7ccd7936 C++: Upgrade to path problem. 2021-09-13 13:52:12 +01:00
Geoffrey White
f58177f292 C++: Full dataflow version. 2021-09-13 10:53:09 +01:00
Felicity Chapman
1d76578202 Merge pull request #6659 from github/docs-311-update-version
Update version numbers for LGTM Enterprise 1.28
2021-09-13 10:26:52 +01:00
Geoffrey White
e696eaaa2f C++: Fix false positives involving STDIN_FILENO. 2021-09-13 09:50:19 +01:00
Geoffrey White
3ba9e80635 C++: Support various functions / variants. 2021-09-13 09:50:03 +01:00
Geoffrey White
1707d67adb C++: Support 'send' as well. 2021-09-13 09:49:40 +01:00
Geoffrey White
29ad3bf7f8 C++: Test dataflow and other slightly more complex cases. 2021-09-13 09:49:25 +01:00
Anders Fugmann
2c93bce9ad C++: Refactor code to use predicate isGuardPhi/4 2021-09-10 10:53:48 +02:00
Felicity Chapman
3b3350e648 Correct the Qllexer path for slides 2021-09-10 08:04:07 +01:00
Felicity Chapman
32b3e416b3 Update version numbers for LGTM E 1.28 2021-09-10 06:54:36 +01:00
Rasmus Lerchedahl Petersen
6c5596d17e Python: rewrite test 2021-09-09 13:45:44 +02:00
Rasmus Lerchedahl Petersen
e27b3162e5 Python: rewrite simpleLocalFlowStep
to take into account the split between
import time and runtime.
2021-09-09 12:43:08 +02:00
Rasmus Lerchedahl Petersen
a9c409403c Python: more tests and comments 2021-09-08 14:44:36 +02:00
Rasmus Lerchedahl Petersen
9b198c6d0a Python: Add some module initialization tests 2021-09-08 10:37:28 +02:00
jorgectf
eee9b3f39e Merge remote-tracking branch 'origin/main' into jorgectf/python/headerInjection 2021-09-07 19:54:58 +02:00
jorgectf
352eab0eca Fix HeaderDeclaration class' comment 2021-09-07 19:44:25 +02:00
Jorge
190bc2f0da Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-09-07 19:42:37 +02:00
Geoffrey White
cd5a5347fc C++: Add basic test. 2021-09-06 18:11:34 +01:00
Geoffrey White
246302453f C++: Add CleartextTransmission query. 2021-09-06 18:11:19 +01:00
jorgectf
8d0386b049 Split into getNameArg and getValueArg 2021-07-25 04:35:22 +02:00
haby0
e8d0827916 Add tornado source 2021-07-05 10:42:15 +08:00
haby0
b866f1b21e Add CWE-348 ClientSuppliedIpUsedInSecurityCheck 2021-07-02 19:30:33 +08:00
jorgectf
b10ade17be Update HeaderDeclaration input naming 2021-06-20 00:13:59 +02:00
jorgectf
017a778a20 Polish make_response and fix extend argument 2021-06-18 20:21:11 +02:00
jorgectf
eac5254a88 Resolve merge conflict 2021-06-18 02:12:49 +02:00
jorgectf
dcb1da338b Extend documentation 2021-06-18 02:03:56 +02:00
jorgectf
4963caf506 Rewrite frameworks modeling 2021-06-18 02:03:27 +02:00
jorgectf
066504e79e Checkout Stdlib.qll 2021-06-18 02:02:47 +02:00
luchua-bc
7af1984348 Update the change note 2021-05-17 11:35:35 +00:00
luchua-bc
1a072f3bb9 Move APIs from predicates flagged auto-generated to the other section 2021-05-14 20:38:23 +00:00
luchua-bc
9ef58e378c Remove the sample Java file in the src folder 2021-05-14 11:01:25 +00:00
luchua-bc
4d014717b6 Add a change note and reset the qhelp file 2021-05-12 15:50:40 +00:00
luchua-bc
fc7d340a89 Query to detect hard-coded Azure credentials 2021-05-07 13:16:41 +00:00
jorgectf
f02c2855ad Generate .expected 2021-04-09 01:28:38 +02:00
jorgectf
632dc61d5e Create qlref 2021-04-09 01:28:22 +02:00
jorgectf
e9c4574552 Apply structure 2021-04-09 01:26:53 +02:00
jorgectf
789c5857fa Create qhelp example 2021-04-09 01:26:28 +02:00
jorgectf
ce3fb6be21 Improve qhelp 2021-04-09 01:26:16 +02:00
jorgectf
b0c498629a Init restructuring 2021-04-09 01:02:03 +02:00
jorgectf
6158dd6bce Finish Sinks 2021-04-09 01:02:02 +02:00
jorgectf
bd894ae8b3 Fix flask test 2021-04-09 01:02:02 +02:00
jorgectf
3be916e82b Polish FlaskHeaderCall 2021-04-09 01:02:01 +02:00
jorgectf
46c5cb1136 Polish WerkzeugHeaderCall 2021-04-09 01:02:00 +02:00
jorgectf
6f89b3f3d9 Init Header Injection query 2021-04-09 01:02:00 +02:00
1678 changed files with 73038 additions and 22519 deletions

View File

@@ -5,5 +5,7 @@
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml", "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"*/ql/examples/qlpack.yml", "*/ql/examples/qlpack.yml",
"*/upgrades/qlpack.yml", "*/upgrades/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"misc/legacy-support/*/qlpack.yml", "misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml" ] } "misc/suite-helpers/qlpack.yml" ] }

4
.github/labeler.yml vendored
View File

@@ -18,6 +18,10 @@ Python:
- python/**/* - python/**/*
- change-notes/**/*python* - change-notes/**/*python*
Ruby:
- ruby/**/*
- change-notes/**/*ruby*
documentation: documentation:
- "**/*.qhelp" - "**/*.qhelp"
- "**/*.md" - "**/*.md"

View File

@@ -6,6 +6,8 @@ on:
- '.github/workflows/csv-coverage-pr-comment.yml' - '.github/workflows/csv-coverage-pr-comment.yml'
- '*/ql/src/**/*.ql' - '*/ql/src/**/*.ql'
- '*/ql/src/**/*.qll' - '*/ql/src/**/*.qll'
- '*/ql/lib/**/*.ql'
- '*/ql/lib/**/*.qll'
- 'misc/scripts/library-coverage/*.py' - 'misc/scripts/library-coverage/*.py'
# input data files # input data files
- '*/documentation/library-coverage/cwe-sink.csv' - '*/documentation/library-coverage/cwe-sink.csv'

3
.gitignore vendored
View File

@@ -24,3 +24,6 @@
/codeql/ /codeql/
csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
# Avoid committing cached package components
.codeql

View File

@@ -4,8 +4,8 @@ This open source repository contains the standard CodeQL libraries and queries t
## How do I learn CodeQL and run queries? ## How do I learn CodeQL and run queries?
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL. There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL.
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode.html) extension to try out your queries on any open source project that's currently being analyzed. You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) extension to try out your queries on any open source project that's currently being analyzed.
## Contributing ## Contributing

View File

@@ -373,6 +373,7 @@
], ],
"Inline Test Expectations": [ "Inline Test Expectations": [
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll", "cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"csharp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"java/ql/test/TestUtilities/InlineExpectationsTest.qll", "java/ql/test/TestUtilities/InlineExpectationsTest.qll",
"python/ql/test/TestUtilities/InlineExpectationsTest.qll", "python/ql/test/TestUtilities/InlineExpectationsTest.qll",
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll" "ruby/ql/test/TestUtilities/InlineExpectationsTest.qll"
@@ -478,5 +479,13 @@
"TypeTracker": [ "TypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll", "python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll" "ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
],
"CodeQL Tutorial": [
"cpp/ql/lib/tutorial.qll",
"csharp/ql/lib/tutorial.qll",
"java/ql/lib/tutorial.qll",
"javascript/ql/lib/tutorial.qll",
"python/ql/lib/tutorial.qll",
"ruby/ql/lib/tutorial.qll"
] ]
} }

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* A new query (`cpp/cleartext-transmission`) has been added. This is similar to the `cpp/cleartext-storage-file`, `cpp/cleartext-storage-buffer` and `cpp/cleartext-storage-database` queries but looks for cases where sensitive information is most likely transmitted over a network.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The "Uncontrolled data used in OS command" (`cpp/command-line-injection`) query has been enhanced to reduce false positive results and its `@precision` increased to `high`

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* Increase precision to high for the "Static buffer overflow" query
(`cpp/static-buffer-overflow`). This means the query is run and displayed by default on Code Scanning and LGTM.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Several improvements made to the `NullTermination.qll` library and the 'Potential improper null termination' (cpp/improper-null-termination). These changes reduce the number of false positive results for this query and related query 'User-controlled data may not be null terminated' (cpp/user-controlled-null-termination-tainted).

View File

@@ -0,0 +1,3 @@
codescanning
* Problems with extraction that in most cases won't break the analysis in a significant way are now reported as warnings rather than errors.
* The failed extractor invocations query now has severity `error`.

View File

@@ -52,11 +52,8 @@ module PrivateCleartextWrite {
class WriteSink extends Sink { class WriteSink extends Sink {
WriteSink() { WriteSink() {
exists(FileWrite f, BufferWrite b | this.asExpr() = any(FileWrite f).getASource() or
this.asExpr() = f.getASource() this.asExpr() = any(BufferWrite b).getAChild()
or
this.asExpr() = b.getAChild()
)
} }
} }
} }

View File

@@ -13,26 +13,25 @@ import cpp
/** A string for `match` that identifies strings that look like they represent private data. */ /** A string for `match` that identifies strings that look like they represent private data. */
private string privateNames() { private string privateNames() {
// Inspired by the list on https://cwe.mitre.org/data/definitions/359.html result =
// Government identifiers, such as Social Security Numbers [
result = "%social%security%number%" or // Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
// Contact information, such as home addresses and telephone numbers // Government identifiers, such as Social Security Numbers
result = "%postcode%" or "%social%security%number%",
result = "%zipcode%" or // Contact information, such as home addresses and telephone numbers
// result = "%telephone%" or "%postcode%", "%zipcode%",
// Geographic location - where the user is (or was) // result = "%telephone%" or
result = "%latitude%" or // Geographic location - where the user is (or was)
result = "%longitude%" or "%latitude%", "%longitude%",
// Financial data - such as credit card numbers, salary, bank accounts, and debts // Financial data - such as credit card numbers, salary, bank accounts, and debts
result = "%creditcard%" or "%creditcard%", "%salary%", "%bankaccount%",
result = "%salary%" or // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
result = "%bankaccount%" or // result = "%email%" or
// Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. // result = "%mobile%" or
// result = "%email%" or "%employer%",
// result = "%mobile%" or // Health - medical conditions, insurance status, prescription records
result = "%employer%" or "%medical%"
// Health - medical conditions, insurance status, prescription records ]
result = "%medical%"
} }
/** An expression that might contain private data. */ /** An expression that might contain private data. */

View File

@@ -15,7 +15,7 @@ class ExternalData extends @externalDataElement {
* Gets the path of the file this data was loaded from, with its * Gets the path of the file this data was loaded from, with its
* extension replaced by `.ql`. * extension replaced by `.ql`.
*/ */
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } string getQueryPath() { result = this.getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
/** Gets the number of fields in this data item. */ /** Gets the number of fields in this data item. */
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) } int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
@@ -24,22 +24,22 @@ class ExternalData extends @externalDataElement {
string getField(int i) { externalData(this, _, i, result) } string getField(int i) { externalData(this, _, i, result) }
/** Gets the integer value of the `i`th field of this data item. */ /** Gets the integer value of the `i`th field of this data item. */
int getFieldAsInt(int i) { result = getField(i).toInt() } int getFieldAsInt(int i) { result = this.getField(i).toInt() }
/** Gets the floating-point value of the `i`th field of this data item. */ /** Gets the floating-point value of the `i`th field of this data item. */
float getFieldAsFloat(int i) { result = getField(i).toFloat() } float getFieldAsFloat(int i) { result = this.getField(i).toFloat() }
/** Gets the value of the `i`th field of this data item, interpreted as a date. */ /** Gets the value of the `i`th field of this data item, interpreted as a date. */
date getFieldAsDate(int i) { result = getField(i).toDate() } date getFieldAsDate(int i) { result = this.getField(i).toDate() }
/** Gets a textual representation of this data item. */ /** Gets a textual representation of this data item. */
string toString() { result = getQueryPath() + ": " + buildTupleString(0) } string toString() { result = this.getQueryPath() + ": " + this.buildTupleString(0) }
/** Gets a textual representation of this data item, starting with the `n`th field. */ /** Gets a textual representation of this data item, starting with the `n`th field. */
private string buildTupleString(int n) { private string buildTupleString(int n) {
n = getNumFields() - 1 and result = getField(n) n = this.getNumFields() - 1 and result = this.getField(n)
or or
n < getNumFields() - 1 and result = getField(n) + "," + buildTupleString(n + 1) n < this.getNumFields() - 1 and result = this.getField(n) + "," + this.buildTupleString(n + 1)
} }
} }
@@ -53,8 +53,8 @@ class DefectExternalData extends ExternalData {
} }
/** Gets the URL associated with this data item. */ /** Gets the URL associated with this data item. */
string getURL() { result = getField(0) } string getURL() { result = this.getField(0) }
/** Gets the message associated with this data item. */ /** Gets the message associated with this data item. */
string getMessage() { result = getField(1) } string getMessage() { result = this.getField(1) }
} }

View File

@@ -269,13 +269,13 @@ class Class extends UserType {
* DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that * DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that
* `= default` members are no longer included. * `= default` members are no longer included.
*/ */
deprecated predicate hasGeneratedCopyConstructor() { hasImplicitCopyConstructor() } deprecated predicate hasGeneratedCopyConstructor() { this.hasImplicitCopyConstructor() }
/** /**
* DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to * DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to
* reflect that `= default` members are no longer included. * reflect that `= default` members are no longer included.
*/ */
deprecated predicate hasGeneratedCopyAssignmentOperator() { hasImplicitCopyConstructor() } deprecated predicate hasGeneratedCopyAssignmentOperator() { this.hasImplicitCopyConstructor() }
/** /**
* Holds if this class, struct or union has an implicitly-declared copy * Holds if this class, struct or union has an implicitly-declared copy
@@ -487,7 +487,7 @@ class Class extends UserType {
exists(ClassDerivation cd | exists(ClassDerivation cd |
// Add the offset of the direct base class and the offset of `baseClass` // Add the offset of the direct base class and the offset of `baseClass`
// within that direct base class. // within that direct base class.
cd = getADerivation() and cd = this.getADerivation() and
result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset() result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset()
) )
} }
@@ -502,12 +502,12 @@ class Class extends UserType {
*/ */
int getABaseClassByteOffset(Class baseClass) { int getABaseClassByteOffset(Class baseClass) {
// Handle the non-virtual case. // Handle the non-virtual case.
result = getANonVirtualBaseClassByteOffset(baseClass) result = this.getANonVirtualBaseClassByteOffset(baseClass)
or or
exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase | exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase |
// Look for the base class as a non-virtual base of a direct or indirect // Look for the base class as a non-virtual base of a direct or indirect
// virtual base, adding the two offsets. // virtual base, adding the two offsets.
getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and this.getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and
offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and
result = virtualBaseOffset + offsetFromVirtualBase result = virtualBaseOffset + offsetFromVirtualBase
) )
@@ -623,11 +623,11 @@ class Class extends UserType {
* inherits one). * inherits one).
*/ */
predicate isPolymorphic() { predicate isPolymorphic() {
exists(MemberFunction f | f.getDeclaringType() = getABaseClass*() and f.isVirtual()) exists(MemberFunction f | f.getDeclaringType() = this.getABaseClass*() and f.isVirtual())
} }
override predicate involvesTemplateParameter() { override predicate involvesTemplateParameter() {
getATemplateArgument().(Type).involvesTemplateParameter() this.getATemplateArgument().(Type).involvesTemplateParameter()
} }
/** Holds if this class, struct or union was declared 'final'. */ /** Holds if this class, struct or union was declared 'final'. */
@@ -765,7 +765,7 @@ class ClassDerivation extends Locatable, @derivation {
* }; * };
* ``` * ```
*/ */
Class getBaseClass() { result = getBaseType().getUnderlyingType() } Class getBaseClass() { result = this.getBaseType().getUnderlyingType() }
override string getAPrimaryQlClass() { result = "ClassDerivation" } override string getAPrimaryQlClass() { result = "ClassDerivation" }
@@ -818,7 +818,7 @@ class ClassDerivation extends Locatable, @derivation {
predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) } predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) }
/** Holds if the derivation is for a virtual base class. */ /** Holds if the derivation is for a virtual base class. */
predicate isVirtual() { hasSpecifier("virtual") } predicate isVirtual() { this.hasSpecifier("virtual") }
/** Gets the location of the derivation. */ /** Gets the location of the derivation. */
override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) } override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) }
@@ -846,7 +846,7 @@ class ClassDerivation extends Locatable, @derivation {
* ``` * ```
*/ */
class LocalClass extends Class { class LocalClass extends Class {
LocalClass() { isLocal() } LocalClass() { this.isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" } override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
@@ -989,9 +989,9 @@ class ClassTemplateSpecialization extends Class {
TemplateClass getPrimaryTemplate() { TemplateClass getPrimaryTemplate() {
// Ignoring template arguments, the primary template has the same name // Ignoring template arguments, the primary template has the same name
// as each of its specializations. // as each of its specializations.
result.getSimpleName() = getSimpleName() and result.getSimpleName() = this.getSimpleName() and
// It is in the same namespace as its specializations. // It is in the same namespace as its specializations.
result.getNamespace() = getNamespace() and result.getNamespace() = this.getNamespace() and
// It is distinguished by the fact that each of its template arguments // It is distinguished by the fact that each of its template arguments
// is a distinct template parameter. // is a distinct template parameter.
count(TemplateParameter tp | tp = result.getATemplateArgument()) = count(TemplateParameter tp | tp = result.getATemplateArgument()) =
@@ -1108,7 +1108,7 @@ deprecated class Interface extends Class {
* ``` * ```
*/ */
class VirtualClassDerivation extends ClassDerivation { class VirtualClassDerivation extends ClassDerivation {
VirtualClassDerivation() { hasSpecifier("virtual") } VirtualClassDerivation() { this.hasSpecifier("virtual") }
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" } override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
} }
@@ -1136,7 +1136,7 @@ class VirtualBaseClass extends Class {
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this } VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
/** A class/struct that is derived from this one using virtual inheritance. */ /** A class/struct that is derived from this one using virtual inheritance. */
Class getAVirtuallyDerivedClass() { result = getAVirtualDerivation().getDerivedClass() } Class getAVirtuallyDerivedClass() { result = this.getAVirtualDerivation().getDerivedClass() }
} }
/** /**
@@ -1155,7 +1155,7 @@ class ProxyClass extends UserType {
override string getAPrimaryQlClass() { result = "ProxyClass" } override string getAPrimaryQlClass() { result = "ProxyClass" }
/** Gets the location of the proxy class. */ /** Gets the location of the proxy class. */
override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() } override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() }
/** Gets the template parameter for which this is the proxy class. */ /** Gets the template parameter for which this is the proxy class. */
TemplateParameter getTemplateParameter() { TemplateParameter getTemplateParameter() {

View File

@@ -184,7 +184,7 @@ class Declaration extends Locatable, @declaration {
predicate hasDefinition() { exists(this.getDefinition()) } predicate hasDefinition() { exists(this.getDefinition()) }
/** DEPRECATED: Use `hasDefinition` instead. */ /** DEPRECATED: Use `hasDefinition` instead. */
predicate isDefined() { hasDefinition() } predicate isDefined() { this.hasDefinition() }
/** Gets the preferred location of this declaration, if any. */ /** Gets the preferred location of this declaration, if any. */
override Location getLocation() { none() } override Location getLocation() { none() }
@@ -209,7 +209,7 @@ class Declaration extends Locatable, @declaration {
predicate isStatic() { this.hasSpecifier("static") } predicate isStatic() { this.hasSpecifier("static") }
/** Holds if this declaration is a member of a class/struct/union. */ /** Holds if this declaration is a member of a class/struct/union. */
predicate isMember() { hasDeclaringType() } predicate isMember() { this.hasDeclaringType() }
/** Holds if this declaration is a member of a class/struct/union. */ /** Holds if this declaration is a member of a class/struct/union. */
predicate hasDeclaringType() { exists(this.getDeclaringType()) } predicate hasDeclaringType() { exists(this.getDeclaringType()) }
@@ -226,14 +226,14 @@ class Declaration extends Locatable, @declaration {
* When called on a template, this will return a template parameter type for * When called on a template, this will return a template parameter type for
* both typed and non-typed parameters. * both typed and non-typed parameters.
*/ */
final Locatable getATemplateArgument() { result = getTemplateArgument(_) } final Locatable getATemplateArgument() { result = this.getTemplateArgument(_) }
/** /**
* Gets a template argument used to instantiate this declaration from a template. * Gets a template argument used to instantiate this declaration from a template.
* When called on a template, this will return a non-typed template * When called on a template, this will return a non-typed template
* parameter value. * parameter value.
*/ */
final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) } final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
/** /**
* Gets the `i`th template argument used to instantiate this declaration from a * Gets the `i`th template argument used to instantiate this declaration from a
@@ -252,9 +252,9 @@ class Declaration extends Locatable, @declaration {
* `getTemplateArgument(1)` return `1`. * `getTemplateArgument(1)` return `1`.
*/ */
final Locatable getTemplateArgument(int index) { final Locatable getTemplateArgument(int index) {
if exists(getTemplateArgumentValue(index)) if exists(this.getTemplateArgumentValue(index))
then result = getTemplateArgumentValue(index) then result = this.getTemplateArgumentValue(index)
else result = getTemplateArgumentType(index) else result = this.getTemplateArgumentType(index)
} }
/** /**
@@ -275,14 +275,13 @@ class Declaration extends Locatable, @declaration {
* `getTemplateArgumentKind(0)`. * `getTemplateArgumentKind(0)`.
*/ */
final Locatable getTemplateArgumentKind(int index) { final Locatable getTemplateArgumentKind(int index) {
if exists(getTemplateArgumentValue(index)) exists(this.getTemplateArgumentValue(index)) and
then result = getTemplateArgumentType(index) result = this.getTemplateArgumentType(index)
else none()
} }
/** Gets the number of template arguments for this declaration. */ /** Gets the number of template arguments for this declaration. */
final int getNumberOfTemplateArguments() { final int getNumberOfTemplateArguments() {
result = count(int i | exists(getTemplateArgument(i))) result = count(int i | exists(this.getTemplateArgument(i)))
} }
private Type getTemplateArgumentType(int index) { private Type getTemplateArgumentType(int index) {
@@ -328,9 +327,9 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
* available), or the name declared by this entry otherwise. * available), or the name declared by this entry otherwise.
*/ */
string getCanonicalName() { string getCanonicalName() {
if getDeclaration().hasDefinition() if this.getDeclaration().hasDefinition()
then result = getDeclaration().getDefinition().getName() then result = this.getDeclaration().getDefinition().getName()
else result = getName() else result = this.getName()
} }
/** /**
@@ -371,18 +370,18 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
/** /**
* Holds if this declaration entry has a specifier with the given name. * Holds if this declaration entry has a specifier with the given name.
*/ */
predicate hasSpecifier(string specifier) { getASpecifier() = specifier } predicate hasSpecifier(string specifier) { this.getASpecifier() = specifier }
/** Holds if this declaration entry is a definition. */ /** Holds if this declaration entry is a definition. */
predicate isDefinition() { none() } // overridden in subclasses predicate isDefinition() { none() } // overridden in subclasses
override string toString() { override string toString() {
if isDefinition() if this.isDefinition()
then result = "definition of " + getName() then result = "definition of " + this.getName()
else else
if getName() = getCanonicalName() if this.getName() = this.getCanonicalName()
then result = "declaration of " + getName() then result = "declaration of " + this.getName()
else result = "declaration of " + getCanonicalName() + " as " + getName() else result = "declaration of " + this.getCanonicalName() + " as " + this.getName()
} }
} }
@@ -581,7 +580,7 @@ private class DirectAccessHolder extends Element {
// transitive closure with a restricted base case. // transitive closure with a restricted base case.
this.thisCanAccessClassStep(base, derived) this.thisCanAccessClassStep(base, derived)
or or
exists(Class between | thisCanAccessClassTrans(base, between) | exists(Class between | this.thisCanAccessClassTrans(base, between) |
isDirectPublicBaseOf(between, derived) or isDirectPublicBaseOf(between, derived) or
this.thisCanAccessClassStep(between, derived) this.thisCanAccessClassStep(between, derived)
) )

View File

@@ -61,7 +61,7 @@ class ElementBase extends @element {
/** /**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*/ */
final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
/** /**
* Gets the name of a primary CodeQL class to which this element belongs. * Gets the name of a primary CodeQL class to which this element belongs.
@@ -206,9 +206,9 @@ class Element extends ElementBase {
/** Gets the closest `Element` enclosing this one. */ /** Gets the closest `Element` enclosing this one. */
cached cached
Element getEnclosingElement() { Element getEnclosingElement() {
result = getEnclosingElementPref() result = this.getEnclosingElementPref()
or or
not exists(getEnclosingElementPref()) and not exists(this.getEnclosingElementPref()) and
( (
this = result.(Class).getAMember() this = result.(Class).getAMember()
or or
@@ -281,7 +281,7 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
* ``` * ```
*/ */
class StaticAssert extends Locatable, @static_assert { class StaticAssert extends Locatable, @static_assert {
override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" } override string toString() { result = "static_assert(..., \"" + this.getMessage() + "\")" }
/** /**
* Gets the expression which this static assertion ensures is true. * Gets the expression which this static assertion ensures is true.

View File

@@ -85,7 +85,7 @@ class Enum extends UserType, IntegralOrEnumType {
* ``` * ```
*/ */
class LocalEnum extends Enum { class LocalEnum extends Enum {
LocalEnum() { isLocal() } LocalEnum() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalEnum" } override string getAPrimaryQlClass() { result = "LocalEnum" }
} }

View File

@@ -38,7 +38,7 @@ class Container extends Locatable, @container {
* DEPRECATED: Use `getLocation` instead. * DEPRECATED: Use `getLocation` instead.
* Gets a URL representing the location of this container. * Gets a URL representing the location of this container.
* *
* For more information see [Providing URLs](https://help.semmle.com/QL/learn-ql/ql/locations.html#providing-urls). * For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/ */
deprecated string getURL() { none() } // overridden by subclasses deprecated string getURL() { none() } // overridden by subclasses
@@ -52,7 +52,7 @@ class Container extends Locatable, @container {
*/ */
string getRelativePath() { string getRelativePath() {
exists(string absPath, string pref | exists(string absPath, string pref |
absPath = getAbsolutePath() and sourceLocationPrefix(pref) absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
| |
absPath = pref and result = "" absPath = pref and result = ""
or or
@@ -79,7 +79,7 @@ class Container extends Locatable, @container {
* </table> * </table>
*/ */
string getBaseName() { string getBaseName() {
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
} }
/** /**
@@ -105,7 +105,9 @@ class Container extends Locatable, @container {
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr> * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
* </table> * </table>
*/ */
string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } string getExtension() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
}
/** /**
* Gets the stem of this container, that is, the prefix of its base name up to * Gets the stem of this container, that is, the prefix of its base name up to
@@ -124,7 +126,9 @@ class Container extends Locatable, @container {
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr> * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table> * </table>
*/ */
string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
}
/** Gets the parent container of this file or folder, if any. */ /** Gets the parent container of this file or folder, if any. */
Container getParentContainer() { Container getParentContainer() {
@@ -135,20 +139,20 @@ class Container extends Locatable, @container {
Container getAChildContainer() { this = result.getParentContainer() } Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */ /** Gets a file in this container. */
File getAFile() { result = getAChildContainer() } File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */ /** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) { File getFile(string baseName) {
result = getAFile() and result = this.getAFile() and
result.getBaseName() = baseName result.getBaseName() = baseName
} }
/** Gets a sub-folder in this container. */ /** Gets a sub-folder in this container. */
Folder getAFolder() { result = getAChildContainer() } Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */ /** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) { Folder getFolder(string baseName) {
result = getAFolder() and result = this.getAFolder() and
result.getBaseName() = baseName result.getBaseName() = baseName
} }
@@ -157,7 +161,7 @@ class Container extends Locatable, @container {
* *
* This is the absolute path of the container. * This is the absolute path of the container.
*/ */
override string toString() { result = getAbsolutePath() } override string toString() { result = this.getAbsolutePath() }
} }
/** /**

View File

@@ -43,26 +43,26 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/ */
string getFullSignature() { string getFullSignature() {
exists(string name, string templateArgs, string args | exists(string name, string templateArgs, string args |
result = name + templateArgs + args + " -> " + getType().toString() and result = name + templateArgs + args + " -> " + this.getType().toString() and
name = getQualifiedName() and name = this.getQualifiedName() and
( (
if exists(getATemplateArgument()) if exists(this.getATemplateArgument())
then then
templateArgs = templateArgs =
"<" + "<" +
concat(int i | concat(int i |
exists(getTemplateArgument(i)) exists(this.getTemplateArgument(i))
| |
getTemplateArgument(i).toString(), ", " order by i this.getTemplateArgument(i).toString(), ", " order by i
) + ">" ) + ">"
else templateArgs = "" else templateArgs = ""
) and ) and
args = args =
"(" + "(" +
concat(int i | concat(int i |
exists(getParameter(i)) exists(this.getParameter(i))
| |
getParameter(i).getType().toString(), ", " order by i this.getParameter(i).getType().toString(), ", " order by i
) + ")" ) + ")"
) )
} }
@@ -70,7 +70,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
/** Gets a specifier of this function. */ /** Gets a specifier of this function. */
override Specifier getASpecifier() { override Specifier getASpecifier() {
funspecifiers(underlyingElement(this), unresolveElement(result)) or funspecifiers(underlyingElement(this), unresolveElement(result)) or
result.hasName(getADeclarationEntry().getASpecifier()) result.hasName(this.getADeclarationEntry().getASpecifier())
} }
/** Gets an attribute of this function. */ /** Gets an attribute of this function. */
@@ -149,7 +149,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Holds if this function is declared with `__attribute__((naked))` or * Holds if this function is declared with `__attribute__((naked))` or
* `__declspec(naked)`. * `__declspec(naked)`.
*/ */
predicate isNaked() { getAnAttribute().hasName("naked") } predicate isNaked() { this.getAnAttribute().hasName("naked") }
/** /**
* Holds if this function has a trailing return type. * Holds if this function has a trailing return type.
@@ -172,7 +172,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Gets the return type of this function after specifiers have been deeply * Gets the return type of this function after specifiers have been deeply
* stripped and typedefs have been resolved. * stripped and typedefs have been resolved.
*/ */
Type getUnspecifiedType() { result = getType().getUnspecifiedType() } Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() }
/** /**
* Gets the nth parameter of this function. There is no result for the * Gets the nth parameter of this function. There is no result for the
@@ -206,7 +206,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
int getEffectiveNumberOfParameters() { int getEffectiveNumberOfParameters() {
// This method is overridden in `MemberFunction`, where the result is // This method is overridden in `MemberFunction`, where the result is
// adjusted to account for the implicit `this` parameter. // adjusted to account for the implicit `this` parameter.
result = getNumberOfParameters() result = this.getNumberOfParameters()
} }
/** /**
@@ -216,7 +216,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* return `int p1, int p2`. * return `int p1, int p2`.
*/ */
string getParameterString() { string getParameterString() {
result = concat(int i | | min(getParameter(i).getTypedName()), ", " order by i) result = concat(int i | | min(this.getParameter(i).getTypedName()), ", " order by i)
} }
/** Gets a call to this function. */ /** Gets a call to this function. */
@@ -229,7 +229,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/ */
override FunctionDeclarationEntry getADeclarationEntry() { override FunctionDeclarationEntry getADeclarationEntry() {
if fun_decls(_, underlyingElement(this), _, _, _) if fun_decls(_, underlyingElement(this), _, _, _)
then declEntry(result) then this.declEntry(result)
else else
exists(Function f | exists(Function f |
this.isConstructedFrom(f) and this.isConstructedFrom(f) and
@@ -250,7 +250,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Gets the location of a `FunctionDeclarationEntry` corresponding to this * Gets the location of a `FunctionDeclarationEntry` corresponding to this
* declaration. * declaration.
*/ */
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
/** Holds if this Function is a Template specialization. */ /** Holds if this Function is a Template specialization. */
predicate isSpecialization() { predicate isSpecialization() {
@@ -265,14 +265,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* definition, if any. * definition, if any.
*/ */
override FunctionDeclarationEntry getDefinition() { override FunctionDeclarationEntry getDefinition() {
result = getADeclarationEntry() and result = this.getADeclarationEntry() and
result.isDefinition() result.isDefinition()
} }
/** Gets the location of the definition, if any. */ /** Gets the location of the definition, if any. */
override Location getDefinitionLocation() { override Location getDefinitionLocation() {
if exists(getDefinition()) if exists(this.getDefinition())
then result = getDefinition().getLocation() then result = this.getDefinition().getLocation()
else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation()) else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation())
} }
@@ -281,7 +281,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* definition, if possible.) * definition, if possible.)
*/ */
override Location getLocation() { override Location getLocation() {
if exists(getDefinition()) if exists(this.getDefinition())
then result = this.getDefinitionLocation() then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation() else result = this.getADeclarationLocation()
} }
@@ -299,7 +299,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
BlockStmt getBlock() { result.getParentScope() = this } BlockStmt getBlock() { result.getParentScope() = this }
/** Holds if this function has an entry point. */ /** Holds if this function has an entry point. */
predicate hasEntryPoint() { exists(getEntryPoint()) } predicate hasEntryPoint() { exists(this.getEntryPoint()) }
/** /**
* Gets the first node in this function's control flow graph. * Gets the first node in this function's control flow graph.
@@ -392,7 +392,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Holds if this function has C linkage, as specified by one of its * Holds if this function has C linkage, as specified by one of its
* declaration entries. For example: `extern "C" void foo();`. * declaration entries. For example: `extern "C" void foo();`.
*/ */
predicate hasCLinkage() { getADeclarationEntry().hasCLinkage() } predicate hasCLinkage() { this.getADeclarationEntry().hasCLinkage() }
/** /**
* Holds if this function is constructed from `f` as a result * Holds if this function is constructed from `f` as a result
@@ -409,27 +409,27 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* several functions that are not linked together have been compiled. An * several functions that are not linked together have been compiled. An
* example would be a project with many 'main' functions. * example would be a project with many 'main' functions.
*/ */
predicate isMultiplyDefined() { strictcount(getFile()) > 1 } predicate isMultiplyDefined() { strictcount(this.getFile()) > 1 }
/** Holds if this function is a varargs function. */ /** Holds if this function is a varargs function. */
predicate isVarargs() { hasSpecifier("varargs") } predicate isVarargs() { this.hasSpecifier("varargs") }
/** Gets a type that is specified to be thrown by the function. */ /** Gets a type that is specified to be thrown by the function. */
Type getAThrownType() { result = getADeclarationEntry().getAThrownType() } Type getAThrownType() { result = this.getADeclarationEntry().getAThrownType() }
/** /**
* Gets the `i`th type specified to be thrown by the function. * Gets the `i`th type specified to be thrown by the function.
*/ */
Type getThrownType(int i) { result = getADeclarationEntry().getThrownType(i) } Type getThrownType(int i) { result = this.getADeclarationEntry().getThrownType(i) }
/** Holds if the function has an exception specification. */ /** Holds if the function has an exception specification. */
predicate hasExceptionSpecification() { getADeclarationEntry().hasExceptionSpecification() } predicate hasExceptionSpecification() { this.getADeclarationEntry().hasExceptionSpecification() }
/** Holds if this function has a `throw()` exception specification. */ /** Holds if this function has a `throw()` exception specification. */
predicate isNoThrow() { getADeclarationEntry().isNoThrow() } predicate isNoThrow() { this.getADeclarationEntry().isNoThrow() }
/** Holds if this function has a `noexcept` exception specification. */ /** Holds if this function has a `noexcept` exception specification. */
predicate isNoExcept() { getADeclarationEntry().isNoExcept() } predicate isNoExcept() { this.getADeclarationEntry().isNoExcept() }
/** /**
* Gets a function that overloads this one. * Gets a function that overloads this one.
@@ -539,7 +539,7 @@ private predicate candGetAnOverloadNonMember(string name, Namespace namespace, F
*/ */
class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
/** Gets the function which is being declared or defined. */ /** Gets the function which is being declared or defined. */
override Function getDeclaration() { result = getFunction() } override Function getDeclaration() { result = this.getFunction() }
override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" } override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" }
@@ -586,7 +586,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* case, catch) plus the number of branching expressions (`?`, `&&`, * case, catch) plus the number of branching expressions (`?`, `&&`,
* `||`) plus one. * `||`) plus one.
*/ */
int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(getBlock()) } int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(this.getBlock()) }
/** /**
* If this is a function definition, get the block containing the * If this is a function definition, get the block containing the
@@ -594,7 +594,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
*/ */
BlockStmt getBlock() { BlockStmt getBlock() {
this.isDefinition() and this.isDefinition() and
result = getFunction().getBlock() and result = this.getFunction().getBlock() and
result.getFile() = this.getFile() result.getFile() = this.getFile()
} }
@@ -604,7 +604,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
*/ */
pragma[noopt] pragma[noopt]
int getNumberOfLines() { int getNumberOfLines() {
exists(BlockStmt b, Location l, int start, int end, int diff | b = getBlock() | exists(BlockStmt b, Location l, int start, int end, int diff | b = this.getBlock() |
l = b.getLocation() and l = b.getLocation() and
start = l.getStartLine() and start = l.getStartLine() and
end = l.getEndLine() and end = l.getEndLine() and
@@ -618,7 +618,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* declaration. * declaration.
*/ */
ParameterDeclarationEntry getAParameterDeclarationEntry() { ParameterDeclarationEntry getAParameterDeclarationEntry() {
result = getParameterDeclarationEntry(_) result = this.getParameterDeclarationEntry(_)
} }
/** /**
@@ -639,7 +639,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* return 'int p1, int p2'. * return 'int p1, int p2'.
*/ */
string getParameterString() { string getParameterString() {
result = concat(int i | | min(getParameterDeclarationEntry(i).getTypedName()), ", " order by i) result =
concat(int i | | min(this.getParameterDeclarationEntry(i).getTypedName()), ", " order by i)
} }
/** /**
@@ -647,10 +648,10 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* *
* `extern "C" void foo();` * `extern "C" void foo();`
*/ */
predicate hasCLinkage() { getASpecifier() = "c_linkage" } predicate hasCLinkage() { this.getASpecifier() = "c_linkage" }
/** Holds if this declaration entry has a void parameter list. */ /** Holds if this declaration entry has a void parameter list. */
predicate hasVoidParamList() { getASpecifier() = "void_param_list" } predicate hasVoidParamList() { this.getASpecifier() = "void_param_list" }
/** Holds if this declaration is also a definition of its function. */ /** Holds if this declaration is also a definition of its function. */
override predicate isDefinition() { fun_def(underlyingElement(this)) } override predicate isDefinition() { fun_def(underlyingElement(this)) }
@@ -665,7 +666,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
predicate isImplicit() { fun_implicit(underlyingElement(this)) } predicate isImplicit() { fun_implicit(underlyingElement(this)) }
/** Gets a type that is specified to be thrown by the declared function. */ /** Gets a type that is specified to be thrown by the declared function. */
Type getAThrownType() { result = getThrownType(_) } Type getAThrownType() { result = this.getThrownType(_) }
/** /**
* Gets the `i`th type specified to be thrown by the declared function * Gets the `i`th type specified to be thrown by the declared function
@@ -690,8 +691,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
predicate hasExceptionSpecification() { predicate hasExceptionSpecification() {
fun_decl_throws(underlyingElement(this), _, _) or fun_decl_throws(underlyingElement(this), _, _) or
fun_decl_noexcept(underlyingElement(this), _) or fun_decl_noexcept(underlyingElement(this), _) or
isNoThrow() or this.isNoThrow() or
isNoExcept() this.isNoExcept()
} }
/** /**
@@ -763,7 +764,7 @@ class Operator extends Function {
*/ */
class TemplateFunction extends Function { class TemplateFunction extends Function {
TemplateFunction() { TemplateFunction() {
is_function_template(underlyingElement(this)) and exists(getATemplateArgument()) is_function_template(underlyingElement(this)) and exists(this.getATemplateArgument())
} }
override string getAPrimaryQlClass() { result = "TemplateFunction" } override string getAPrimaryQlClass() { result = "TemplateFunction" }

View File

@@ -23,7 +23,7 @@ class Include extends PreprocessorDirective, @ppd_include {
* Gets the token which occurs after `#include`, for example `"filename"` * Gets the token which occurs after `#include`, for example `"filename"`
* or `<filename>`. * or `<filename>`.
*/ */
string getIncludeText() { result = getHead() } string getIncludeText() { result = this.getHead() }
/** Gets the file directly included by this `#include`. */ /** Gets the file directly included by this `#include`. */
File getIncludedFile() { includes(underlyingElement(this), unresolveElement(result)) } File getIncludedFile() { includes(underlyingElement(this), unresolveElement(result)) }
@@ -53,7 +53,7 @@ class Include extends PreprocessorDirective, @ppd_include {
* ``` * ```
*/ */
class IncludeNext extends Include, @ppd_include_next { class IncludeNext extends Include, @ppd_include_next {
override string toString() { result = "#include_next " + getIncludeText() } override string toString() { result = "#include_next " + this.getIncludeText() }
} }
/** /**
@@ -65,5 +65,5 @@ class IncludeNext extends Include, @ppd_include_next {
* ``` * ```
*/ */
class Import extends Include, @ppd_objc_import { class Import extends Include, @ppd_objc_import {
override string toString() { result = "#import " + getIncludeText() } override string toString() { result = "#import " + this.getIncludeText() }
} }

View File

@@ -34,8 +34,8 @@ class Initializer extends ControlFlowNode, @initialiser {
override predicate fromSource() { not this.getLocation() instanceof UnknownLocation } override predicate fromSource() { not this.getLocation() instanceof UnknownLocation }
override string toString() { override string toString() {
if exists(getDeclaration()) if exists(this.getDeclaration())
then result = "initializer for " + max(getDeclaration().getName()) then result = "initializer for " + max(this.getDeclaration().getName())
else result = "initializer" else result = "initializer"
} }

View File

@@ -61,7 +61,7 @@ class Location extends @location {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -79,8 +79,8 @@ class Location extends @location {
/** Holds if location `l` is completely contained within this one. */ /** Holds if location `l` is completely contained within this one. */
predicate subsumes(Location l) { predicate subsumes(Location l) {
exists(File f | f = getFile() | exists(File f | f = this.getFile() |
exists(int thisStart, int thisEnd | charLoc(f, thisStart, thisEnd) | exists(int thisStart, int thisEnd | this.charLoc(f, thisStart, thisEnd) |
exists(int lStart, int lEnd | l.charLoc(f, lStart, lEnd) | exists(int lStart, int lEnd | l.charLoc(f, lStart, lEnd) |
thisStart <= lStart and lEnd <= thisEnd thisStart <= lStart and lEnd <= thisEnd
) )
@@ -97,10 +97,10 @@ class Location extends @location {
* see `subsumes`. * see `subsumes`.
*/ */
predicate charLoc(File f, int start, int end) { predicate charLoc(File f, int start, int end) {
f = getFile() and f = this.getFile() and
exists(int maxCols | maxCols = maxCols(f) | exists(int maxCols | maxCols = maxCols(f) |
start = getStartLine() * maxCols + getStartColumn() and start = this.getStartLine() * maxCols + this.getStartColumn() and
end = getEndLine() * maxCols + getEndColumn() end = this.getEndLine() * maxCols + this.getEndColumn()
) )
} }
} }
@@ -144,7 +144,7 @@ class Locatable extends Element { }
* expressions, one for statements and one for other program elements. * expressions, one for statements and one for other program elements.
*/ */
class UnknownLocation extends Location { class UnknownLocation extends Location {
UnknownLocation() { getFile().getAbsolutePath() = "" } UnknownLocation() { this.getFile().getAbsolutePath() = "" }
} }
/** /**

View File

@@ -44,10 +44,10 @@ class Macro extends PreprocessorDirective, @ppd_define {
* Gets the name of the macro. For example, `MAX` in * Gets the name of the macro. For example, `MAX` in
* `#define MAX(x,y) (((x)>(y))?(x):(y))`. * `#define MAX(x,y) (((x)>(y))?(x):(y))`.
*/ */
string getName() { result = getHead().splitAt("(", 0) } string getName() { result = this.getHead().splitAt("(", 0) }
/** Holds if the macro has name `name`. */ /** Holds if the macro has name `name`. */
predicate hasName(string name) { getName() = name } predicate hasName(string name) { this.getName() = name }
} }
/** /**
@@ -130,7 +130,7 @@ class MacroAccess extends Locatable, @macroinvocation {
override string toString() { result = this.getMacro().getHead() } override string toString() { result = this.getMacro().getHead() }
/** Gets the name of the accessed macro. */ /** Gets the name of the accessed macro. */
string getMacroName() { result = getMacro().getName() } string getMacroName() { result = this.getMacro().getName() }
} }
/** /**
@@ -197,8 +197,8 @@ class MacroInvocation extends MacroAccess {
* expression. In other cases, it may have multiple results or no results. * expression. In other cases, it may have multiple results or no results.
*/ */
Expr getExpr() { Expr getExpr() {
result = getAnExpandedElement() and result = this.getAnExpandedElement() and
not result.getParent() = getAnExpandedElement() and not result.getParent() = this.getAnExpandedElement() and
not result instanceof Conversion not result instanceof Conversion
} }
@@ -208,8 +208,8 @@ class MacroInvocation extends MacroAccess {
* element is not a statement (for example if it is an expression). * element is not a statement (for example if it is an expression).
*/ */
Stmt getStmt() { Stmt getStmt() {
result = getAnExpandedElement() and result = this.getAnExpandedElement() and
not result.getParent() = getAnExpandedElement() not result.getParent() = this.getAnExpandedElement()
} }
/** /**
@@ -278,7 +278,7 @@ deprecated class MacroInvocationExpr extends Expr {
MacroInvocation getInvocation() { result.getExpr() = this } MacroInvocation getInvocation() { result.getExpr() = this }
/** Gets the name of the invoked macro. */ /** Gets the name of the invoked macro. */
string getMacroName() { result = getInvocation().getMacroName() } string getMacroName() { result = this.getInvocation().getMacroName() }
} }
/** /**
@@ -298,7 +298,7 @@ deprecated class MacroInvocationStmt extends Stmt {
MacroInvocation getInvocation() { result.getStmt() = this } MacroInvocation getInvocation() { result.getStmt() = this }
/** Gets the name of the invoked macro. */ /** Gets the name of the invoked macro. */
string getMacroName() { result = getInvocation().getMacroName() } string getMacroName() { result = this.getInvocation().getMacroName() }
} }
/** Holds if `l` is the location of a macro. */ /** Holds if `l` is the location of a macro. */

View File

@@ -36,7 +36,9 @@ class MemberFunction extends Function {
* `this` parameter. * `this` parameter.
*/ */
override int getEffectiveNumberOfParameters() { override int getEffectiveNumberOfParameters() {
if isStatic() then result = getNumberOfParameters() else result = getNumberOfParameters() + 1 if this.isStatic()
then result = this.getNumberOfParameters()
else result = this.getNumberOfParameters() + 1
} }
/** Holds if this member is private. */ /** Holds if this member is private. */
@@ -49,13 +51,13 @@ class MemberFunction extends Function {
predicate isPublic() { this.hasSpecifier("public") } predicate isPublic() { this.hasSpecifier("public") }
/** Holds if this declaration has the lvalue ref-qualifier */ /** Holds if this declaration has the lvalue ref-qualifier */
predicate isLValueRefQualified() { hasSpecifier("&") } predicate isLValueRefQualified() { this.hasSpecifier("&") }
/** Holds if this declaration has the rvalue ref-qualifier */ /** Holds if this declaration has the rvalue ref-qualifier */
predicate isRValueRefQualified() { hasSpecifier("&&") } predicate isRValueRefQualified() { this.hasSpecifier("&&") }
/** Holds if this declaration has a ref-qualifier */ /** Holds if this declaration has a ref-qualifier */
predicate isRefQualified() { isLValueRefQualified() or isRValueRefQualified() } predicate isRefQualified() { this.isLValueRefQualified() or this.isRValueRefQualified() }
/** Holds if this function overrides that function. */ /** Holds if this function overrides that function. */
predicate overrides(MemberFunction that) { predicate overrides(MemberFunction that) {
@@ -73,10 +75,10 @@ class MemberFunction extends Function {
* class body. * class body.
*/ */
FunctionDeclarationEntry getClassBodyDeclarationEntry() { FunctionDeclarationEntry getClassBodyDeclarationEntry() {
if strictcount(getADeclarationEntry()) = 1 if strictcount(this.getADeclarationEntry()) = 1
then result = getDefinition() then result = this.getDefinition()
else ( else (
result = getADeclarationEntry() and result != getDefinition() result = this.getADeclarationEntry() and result != this.getDefinition()
) )
} }
@@ -198,7 +200,7 @@ class Constructor extends MemberFunction {
* compiler-generated action which initializes a base class or member * compiler-generated action which initializes a base class or member
* variable. * variable.
*/ */
ConstructorInit getAnInitializer() { result = getInitializer(_) } ConstructorInit getAnInitializer() { result = this.getInitializer(_) }
/** /**
* Gets an entry in the constructor's initializer list, or a * Gets an entry in the constructor's initializer list, or a
@@ -220,8 +222,8 @@ class ImplicitConversionFunction extends MemberFunction {
functions(underlyingElement(this), _, 4) functions(underlyingElement(this), _, 4)
or or
// ConversionConstructor (deprecated) // ConversionConstructor (deprecated)
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
not hasSpecifier("explicit") not this.hasSpecifier("explicit")
} }
/** Gets the type this `ImplicitConversionFunction` takes as input. */ /** Gets the type this `ImplicitConversionFunction` takes as input. */
@@ -248,8 +250,8 @@ class ImplicitConversionFunction extends MemberFunction {
*/ */
deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction { deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction {
ConversionConstructor() { ConversionConstructor() {
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
not hasSpecifier("explicit") not this.hasSpecifier("explicit")
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -301,15 +303,15 @@ class CopyConstructor extends Constructor {
hasCopySignature(this) and hasCopySignature(this) and
( (
// The rest of the parameters all have default values // The rest of the parameters all have default values
forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer()) forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer())
or or
// or this is a template class, in which case the default values have // or this is a template class, in which case the default values have
// not been extracted even if they exist. In that case, we assume that // not been extracted even if they exist. In that case, we assume that
// there are default values present since that is the most common case // there are default values present since that is the most common case
// in real-world code. // in real-world code.
getDeclaringType() instanceof TemplateClass this.getDeclaringType() instanceof TemplateClass
) and ) and
not exists(getATemplateArgument()) not exists(this.getATemplateArgument())
} }
override string getAPrimaryQlClass() { result = "CopyConstructor" } override string getAPrimaryQlClass() { result = "CopyConstructor" }
@@ -325,8 +327,8 @@ class CopyConstructor extends Constructor {
// type-checked for each template instantiation; if an argument in an // type-checked for each template instantiation; if an argument in an
// instantiation fails to type-check then the corresponding parameter has // instantiation fails to type-check then the corresponding parameter has
// no default argument in the instantiation. // no default argument in the instantiation.
getDeclaringType() instanceof TemplateClass and this.getDeclaringType() instanceof TemplateClass and
getNumberOfParameters() > 1 this.getNumberOfParameters() > 1
} }
} }
@@ -358,15 +360,15 @@ class MoveConstructor extends Constructor {
hasMoveSignature(this) and hasMoveSignature(this) and
( (
// The rest of the parameters all have default values // The rest of the parameters all have default values
forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer()) forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer())
or or
// or this is a template class, in which case the default values have // or this is a template class, in which case the default values have
// not been extracted even if they exist. In that case, we assume that // not been extracted even if they exist. In that case, we assume that
// there are default values present since that is the most common case // there are default values present since that is the most common case
// in real-world code. // in real-world code.
getDeclaringType() instanceof TemplateClass this.getDeclaringType() instanceof TemplateClass
) and ) and
not exists(getATemplateArgument()) not exists(this.getATemplateArgument())
} }
override string getAPrimaryQlClass() { result = "MoveConstructor" } override string getAPrimaryQlClass() { result = "MoveConstructor" }
@@ -382,8 +384,8 @@ class MoveConstructor extends Constructor {
// type-checked for each template instantiation; if an argument in an // type-checked for each template instantiation; if an argument in an
// instantiation fails to type-check then the corresponding parameter has // instantiation fails to type-check then the corresponding parameter has
// no default argument in the instantiation. // no default argument in the instantiation.
getDeclaringType() instanceof TemplateClass and this.getDeclaringType() instanceof TemplateClass and
getNumberOfParameters() > 1 this.getNumberOfParameters() > 1
} }
} }
@@ -426,7 +428,7 @@ class Destructor extends MemberFunction {
* Gets a compiler-generated action which destructs a base class or member * Gets a compiler-generated action which destructs a base class or member
* variable. * variable.
*/ */
DestructorDestruction getADestruction() { result = getDestruction(_) } DestructorDestruction getADestruction() { result = this.getDestruction(_) }
/** /**
* Gets a compiler-generated action which destructs a base class or member * Gets a compiler-generated action which destructs a base class or member
@@ -475,16 +477,16 @@ class ConversionOperator extends MemberFunction, ImplicitConversionFunction {
*/ */
class CopyAssignmentOperator extends Operator { class CopyAssignmentOperator extends Operator {
CopyAssignmentOperator() { CopyAssignmentOperator() {
hasName("operator=") and this.hasName("operator=") and
( (
hasCopySignature(this) hasCopySignature(this)
or or
// Unlike CopyConstructor, this member allows a non-reference // Unlike CopyConstructor, this member allows a non-reference
// parameter. // parameter.
getParameter(0).getUnspecifiedType() = getDeclaringType() this.getParameter(0).getUnspecifiedType() = this.getDeclaringType()
) and ) and
not exists(this.getParameter(1)) and not exists(this.getParameter(1)) and
not exists(getATemplateArgument()) not exists(this.getATemplateArgument())
} }
override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" } override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" }
@@ -507,10 +509,10 @@ class CopyAssignmentOperator extends Operator {
*/ */
class MoveAssignmentOperator extends Operator { class MoveAssignmentOperator extends Operator {
MoveAssignmentOperator() { MoveAssignmentOperator() {
hasName("operator=") and this.hasName("operator=") and
hasMoveSignature(this) and hasMoveSignature(this) and
not exists(this.getParameter(1)) and not exists(this.getParameter(1)) and
not exists(getATemplateArgument()) not exists(this.getATemplateArgument())
} }
override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" } override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" }

View File

@@ -38,8 +38,8 @@ class Namespace extends NameQualifyingElement, @namespace {
* unless the namespace has exactly one declaration entry. * unless the namespace has exactly one declaration entry.
*/ */
override Location getLocation() { override Location getLocation() {
if strictcount(getADeclarationEntry()) = 1 if strictcount(this.getADeclarationEntry()) = 1
then result = getADeclarationEntry().getLocation() then result = this.getADeclarationEntry().getLocation()
else result instanceof UnknownDefaultLocation else result instanceof UnknownDefaultLocation
} }
@@ -50,7 +50,7 @@ class Namespace extends NameQualifyingElement, @namespace {
predicate hasName(string name) { name = this.getName() } predicate hasName(string name) { name = this.getName() }
/** Holds if this namespace is anonymous. */ /** Holds if this namespace is anonymous. */
predicate isAnonymous() { hasName("(unnamed namespace)") } predicate isAnonymous() { this.hasName("(unnamed namespace)") }
/** Gets the name of the parent namespace, if it exists. */ /** Gets the name of the parent namespace, if it exists. */
private string getParentName() { private string getParentName() {
@@ -60,9 +60,9 @@ class Namespace extends NameQualifyingElement, @namespace {
/** Gets the qualified name of this namespace. For example: `a::b`. */ /** Gets the qualified name of this namespace. For example: `a::b`. */
string getQualifiedName() { string getQualifiedName() {
if exists(getParentName()) if exists(this.getParentName())
then result = getParentNamespace().getQualifiedName() + "::" + getName() then result = this.getParentNamespace().getQualifiedName() + "::" + this.getName()
else result = getName() else result = this.getName()
} }
/** Gets the parent namespace, if any. */ /** Gets the parent namespace, if any. */
@@ -99,7 +99,7 @@ class Namespace extends NameQualifyingElement, @namespace {
/** Gets a version of the `QualifiedName` that is more suitable for display purposes. */ /** Gets a version of the `QualifiedName` that is more suitable for display purposes. */
string getFriendlyName() { result = this.getQualifiedName() } string getFriendlyName() { result = this.getQualifiedName() }
final override string toString() { result = getFriendlyName() } final override string toString() { result = this.getFriendlyName() }
/** Gets a declaration of (part of) this namespace. */ /** Gets a declaration of (part of) this namespace. */
NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this } NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this }

View File

@@ -40,12 +40,12 @@ class Parameter extends LocalScopeVariable, @parameter {
*/ */
override string getName() { override string getName() {
exists(VariableDeclarationEntry vde | exists(VariableDeclarationEntry vde |
vde = getANamedDeclarationEntry() and result = vde.getName() vde = this.getANamedDeclarationEntry() and result = vde.getName()
| |
vde.isDefinition() or not getANamedDeclarationEntry().isDefinition() vde.isDefinition() or not this.getANamedDeclarationEntry().isDefinition()
) )
or or
not exists(getANamedDeclarationEntry()) and not exists(this.getANamedDeclarationEntry()) and
result = "(unnamed parameter " + this.getIndex().toString() + ")" result = "(unnamed parameter " + this.getIndex().toString() + ")"
} }
@@ -58,8 +58,12 @@ class Parameter extends LocalScopeVariable, @parameter {
*/ */
string getTypedName() { string getTypedName() {
exists(string typeString, string nameString | exists(string typeString, string nameString |
(if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and (
(if exists(getName()) then nameString = getName() else nameString = "") and if exists(this.getType().getName())
then typeString = this.getType().getName()
else typeString = ""
) and
(if exists(this.getName()) then nameString = this.getName() else nameString = "") and
( (
if typeString != "" and nameString != "" if typeString != "" and nameString != ""
then result = typeString + " " + nameString then result = typeString + " " + nameString
@@ -69,7 +73,7 @@ class Parameter extends LocalScopeVariable, @parameter {
} }
private VariableDeclarationEntry getANamedDeclarationEntry() { private VariableDeclarationEntry getANamedDeclarationEntry() {
result = getAnEffectiveDeclarationEntry() and result.getName() != "" result = this.getAnEffectiveDeclarationEntry() and result.getName() != ""
} }
/** /**
@@ -82,13 +86,13 @@ class Parameter extends LocalScopeVariable, @parameter {
* own). * own).
*/ */
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() { private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
if getFunction().isConstructedFrom(_) if this.getFunction().isConstructedFrom(_)
then then
exists(Function prototypeInstantiation | exists(Function prototypeInstantiation |
prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and prototypeInstantiation.getParameter(this.getIndex()) = result.getVariable() and
getFunction().isConstructedFrom(prototypeInstantiation) this.getFunction().isConstructedFrom(prototypeInstantiation)
) )
else result = getADeclarationEntry() else result = this.getADeclarationEntry()
} }
/** /**
@@ -114,7 +118,7 @@ class Parameter extends LocalScopeVariable, @parameter {
* `getName()` is not "(unnamed parameter i)" (where `i` is the index * `getName()` is not "(unnamed parameter i)" (where `i` is the index
* of the parameter). * of the parameter).
*/ */
predicate isNamed() { exists(getANamedDeclarationEntry()) } predicate isNamed() { exists(this.getANamedDeclarationEntry()) }
/** /**
* Gets the function to which this parameter belongs, if it is a function * Gets the function to which this parameter belongs, if it is a function
@@ -157,9 +161,9 @@ class Parameter extends LocalScopeVariable, @parameter {
*/ */
override Location getLocation() { override Location getLocation() {
exists(VariableDeclarationEntry vde | exists(VariableDeclarationEntry vde |
vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation() vde = this.getAnEffectiveDeclarationEntry() and result = vde.getLocation()
| |
vde.isDefinition() or not getAnEffectiveDeclarationEntry().isDefinition() vde.isDefinition() or not this.getAnEffectiveDeclarationEntry().isDefinition()
) )
} }
} }

View File

@@ -29,8 +29,8 @@ class PreprocessorDirective extends Locatable, @preprocdirect {
PreprocessorBranch getAGuard() { PreprocessorBranch getAGuard() {
exists(PreprocessorEndif e, int line | exists(PreprocessorEndif e, int line |
result.getEndIf() = e and result.getEndIf() = e and
e.getFile() = getFile() and e.getFile() = this.getFile() and
result.getFile() = getFile() and result.getFile() = this.getFile() and
line = this.getLocation().getStartLine() and line = this.getLocation().getStartLine() and
result.getLocation().getStartLine() < line and result.getLocation().getStartLine() < line and
line < e.getLocation().getEndLine() line < e.getLocation().getEndLine()
@@ -69,7 +69,9 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
* directives in different translation units, then there can be more than * directives in different translation units, then there can be more than
* one result. * one result.
*/ */
PreprocessorEndif getEndIf() { preprocpair(unresolveElement(getIf()), unresolveElement(result)) } PreprocessorEndif getEndIf() {
preprocpair(unresolveElement(this.getIf()), unresolveElement(result))
}
/** /**
* Gets the next `#elif`, `#else` or `#endif` matching this branching * Gets the next `#elif`, `#else` or `#endif` matching this branching
@@ -137,7 +139,7 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch {
* which evaluated it, or was not taken by any translation unit which * which evaluated it, or was not taken by any translation unit which
* evaluated it. * evaluated it.
*/ */
predicate wasPredictable() { not (wasTaken() and wasNotTaken()) } predicate wasPredictable() { not (this.wasTaken() and this.wasNotTaken()) }
} }
/** /**
@@ -268,7 +270,7 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef {
/** /**
* Gets the name of the macro that is undefined. * Gets the name of the macro that is undefined.
*/ */
string getName() { result = getHead() } string getName() { result = this.getHead() }
} }
/** /**

View File

@@ -105,8 +105,8 @@ private class DumpType extends Type {
// for a `SpecifiedType`, insert the qualifiers after // for a `SpecifiedType`, insert the qualifiers after
// `getDeclaratorSuffixBeforeQualifiers()`. // `getDeclaratorSuffixBeforeQualifiers()`.
result = result =
getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() + this.getTypeSpecifier() + this.getDeclaratorPrefix() +
getDeclaratorSuffix() this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix()
} }
/** /**
@@ -147,29 +147,35 @@ private class DumpType extends Type {
} }
private class BuiltInDumpType extends DumpType, BuiltInType { private class BuiltInDumpType extends DumpType, BuiltInType {
override string getTypeSpecifier() { result = toString() } override string getTypeSpecifier() { result = this.toString() }
} }
private class IntegralDumpType extends BuiltInDumpType, IntegralType { private class IntegralDumpType extends BuiltInDumpType, IntegralType {
override string getTypeSpecifier() { result = getCanonicalArithmeticType().toString() } override string getTypeSpecifier() { result = this.getCanonicalArithmeticType().toString() }
} }
private class DerivedDumpType extends DumpType, DerivedType { private class DerivedDumpType extends DumpType, DerivedType {
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
override string getDeclaratorSuffixBeforeQualifiers() { override string getDeclaratorSuffixBeforeQualifiers() {
result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
} }
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
} }
private class DecltypeDumpType extends DumpType, Decltype { private class DecltypeDumpType extends DumpType, Decltype {
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() } override string getDeclaratorPrefix() {
result = this.getBaseType().(DumpType).getDeclaratorPrefix()
}
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
} }
private class PointerIshDumpType extends DerivedDumpType { private class PointerIshDumpType extends DerivedDumpType {
@@ -180,10 +186,10 @@ private class PointerIshDumpType extends DerivedDumpType {
override string getDeclaratorPrefix() { override string getDeclaratorPrefix() {
exists(string declarator | exists(string declarator |
result = getBaseType().(DumpType).getDeclaratorPrefix() + declarator and result = this.getBaseType().(DumpType).getDeclaratorPrefix() + declarator and
if getBaseType().getUnspecifiedType() instanceof ArrayType if this.getBaseType().getUnspecifiedType() instanceof ArrayType
then declarator = "(" + getDeclaratorToken() + ")" then declarator = "(" + this.getDeclaratorToken() + ")"
else declarator = getDeclaratorToken() else declarator = this.getDeclaratorToken()
) )
} }
@@ -206,13 +212,13 @@ private class RValueReferenceDumpType extends PointerIshDumpType, RValueReferenc
} }
private class PointerToMemberDumpType extends DumpType, PointerToMemberType { private class PointerToMemberDumpType extends DumpType, PointerToMemberType {
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
override string getDeclaratorPrefix() { override string getDeclaratorPrefix() {
exists(string declarator, string parenDeclarator, Type baseType | exists(string declarator, string parenDeclarator, Type baseType |
declarator = getClass().(DumpType).getTypeIdentityString() + "::*" and declarator = this.getClass().(DumpType).getTypeIdentityString() + "::*" and
result = getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and result = this.getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and
baseType = getBaseType().getUnspecifiedType() and baseType = this.getBaseType().getUnspecifiedType() and
if baseType instanceof ArrayType or baseType instanceof RoutineType if baseType instanceof ArrayType or baseType instanceof RoutineType
then parenDeclarator = "(" + declarator then parenDeclarator = "(" + declarator
else parenDeclarator = declarator else parenDeclarator = declarator
@@ -221,38 +227,44 @@ private class PointerToMemberDumpType extends DumpType, PointerToMemberType {
override string getDeclaratorSuffixBeforeQualifiers() { override string getDeclaratorSuffixBeforeQualifiers() {
exists(Type baseType | exists(Type baseType |
baseType = getBaseType().getUnspecifiedType() and baseType = this.getBaseType().getUnspecifiedType() and
if baseType instanceof ArrayType or baseType instanceof RoutineType if baseType instanceof ArrayType or baseType instanceof RoutineType
then result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() then result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() else result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
) )
} }
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
} }
private class ArrayDumpType extends DerivedDumpType, ArrayType { private class ArrayDumpType extends DerivedDumpType, ArrayType {
override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() } override string getDeclaratorPrefix() {
result = this.getBaseType().(DumpType).getDeclaratorPrefix()
}
override string getDeclaratorSuffixBeforeQualifiers() { override string getDeclaratorSuffixBeforeQualifiers() {
if exists(getArraySize()) if exists(this.getArraySize())
then then
result = result =
"[" + getArraySize().toString() + "]" + "[" + this.getArraySize().toString() + "]" +
getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() else result = "[]" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
} }
} }
private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointerIshType { private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointerIshType {
override string getDeclaratorSuffixBeforeQualifiers() { override string getDeclaratorSuffixBeforeQualifiers() {
result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
} }
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
override string getDeclaratorPrefix() { override string getDeclaratorPrefix() {
result = getBaseType().(DumpType).getDeclaratorPrefix() + "(" + getDeclaratorToken() result = this.getBaseType().(DumpType).getDeclaratorPrefix() + "(" + this.getDeclaratorToken()
} }
/** /**
@@ -274,10 +286,10 @@ private class BlockDumpType extends FunctionPointerIshDumpType, BlockType {
} }
private class RoutineDumpType extends DumpType, RoutineType { private class RoutineDumpType extends DumpType, RoutineType {
override string getTypeSpecifier() { result = getReturnType().(DumpType).getTypeSpecifier() } override string getTypeSpecifier() { result = this.getReturnType().(DumpType).getTypeSpecifier() }
override string getDeclaratorPrefix() { override string getDeclaratorPrefix() {
result = getReturnType().(DumpType).getDeclaratorPrefix() result = this.getReturnType().(DumpType).getDeclaratorPrefix()
} }
language[monotonicAggregates] language[monotonicAggregates]
@@ -285,39 +297,41 @@ private class RoutineDumpType extends DumpType, RoutineType {
result = result =
"(" + "(" +
concat(int i | concat(int i |
exists(getParameterType(i)) exists(this.getParameterType(i))
| |
getParameterTypeString(getParameterType(i)), ", " order by i getParameterTypeString(this.getParameterType(i)), ", " order by i
) + ")" ) + ")"
} }
override string getDeclaratorSuffix() { override string getDeclaratorSuffix() {
result = result =
getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + this.getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
getReturnType().(DumpType).getDeclaratorSuffix() this.getReturnType().(DumpType).getDeclaratorSuffix()
} }
} }
private class SpecifiedDumpType extends DerivedDumpType, SpecifiedType { private class SpecifiedDumpType extends DerivedDumpType, SpecifiedType {
override string getDeclaratorPrefix() { override string getDeclaratorPrefix() {
exists(string basePrefix | exists(string basePrefix |
basePrefix = getBaseType().(DumpType).getDeclaratorPrefix() and basePrefix = this.getBaseType().(DumpType).getDeclaratorPrefix() and
if getBaseType().getUnspecifiedType() instanceof RoutineType if this.getBaseType().getUnspecifiedType() instanceof RoutineType
then result = basePrefix then result = basePrefix
else result = basePrefix + " " + getSpecifierString() else result = basePrefix + " " + this.getSpecifierString()
) )
} }
override string getDeclaratorSuffixBeforeQualifiers() { override string getDeclaratorSuffixBeforeQualifiers() {
exists(string baseSuffix | exists(string baseSuffix |
baseSuffix = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and baseSuffix = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and
if getBaseType().getUnspecifiedType() instanceof RoutineType if this.getBaseType().getUnspecifiedType() instanceof RoutineType
then result = baseSuffix + " " + getSpecifierString() then result = baseSuffix + " " + this.getSpecifierString()
else result = baseSuffix else result = baseSuffix
) )
} }
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
} }
private class UserDumpType extends DumpType, DumpDeclaration, UserType { private class UserDumpType extends DumpType, DumpDeclaration, UserType {
@@ -330,18 +344,18 @@ private class UserDumpType extends DumpType, DumpDeclaration, UserType {
// "lambda [] type at line 12, col. 40" // "lambda [] type at line 12, col. 40"
// Use `min(getSimpleName())` to work around an extractor bug where a lambda can have different names // Use `min(getSimpleName())` to work around an extractor bug where a lambda can have different names
// from different compilation units. // from different compilation units.
simpleName = "(" + min(getSimpleName()) + ")" simpleName = "(" + min(this.getSimpleName()) + ")"
else simpleName = getSimpleName() else simpleName = this.getSimpleName()
) and ) and
result = getScopePrefix(this) + simpleName + getTemplateArgumentsString() result = getScopePrefix(this) + simpleName + this.getTemplateArgumentsString()
) )
} }
override string getTypeSpecifier() { result = getIdentityString() } override string getTypeSpecifier() { result = this.getIdentityString() }
} }
private class DumpProxyClass extends UserDumpType, ProxyClass { private class DumpProxyClass extends UserDumpType, ProxyClass {
override string getIdentityString() { result = getName() } override string getIdentityString() { result = this.getName() }
} }
private class DumpVariable extends DumpDeclaration, Variable { private class DumpVariable extends DumpDeclaration, Variable {
@@ -360,9 +374,9 @@ private class DumpVariable extends DumpDeclaration, Variable {
private class DumpFunction extends DumpDeclaration, Function { private class DumpFunction extends DumpDeclaration, Function {
override string getIdentityString() { override string getIdentityString() {
result = result =
getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + " " + this.getType().(DumpType).getTypeSpecifier() + this.getType().(DumpType).getDeclaratorPrefix()
getScopePrefix(this) + getName() + getTemplateArgumentsString() + + " " + getScopePrefix(this) + this.getName() + this.getTemplateArgumentsString() +
getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix() this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix()
} }
language[monotonicAggregates] language[monotonicAggregates]
@@ -370,28 +384,29 @@ private class DumpFunction extends DumpDeclaration, Function {
result = result =
"(" + "(" +
concat(int i | concat(int i |
exists(getParameter(i).getType()) exists(this.getParameter(i).getType())
| |
getParameterTypeString(getParameter(i).getType()), ", " order by i getParameterTypeString(this.getParameter(i).getType()), ", " order by i
) + ")" + getQualifierString() ) + ")" + this.getQualifierString()
} }
private string getQualifierString() { private string getQualifierString() {
if exists(getACVQualifier()) if exists(this.getACVQualifier())
then then
result = " " + strictconcat(string qualifier | qualifier = getACVQualifier() | qualifier, " ") result =
" " + strictconcat(string qualifier | qualifier = this.getACVQualifier() | qualifier, " ")
else result = "" else result = ""
} }
private string getACVQualifier() { private string getACVQualifier() {
result = getASpecifier().getName() and result = this.getASpecifier().getName() and
result = ["const", "volatile"] result = ["const", "volatile"]
} }
private string getDeclaratorSuffix() { private string getDeclaratorSuffix() {
result = result =
getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + this.getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
getType().(DumpType).getDeclaratorSuffix() this.getType().(DumpType).getDeclaratorSuffix()
} }
} }

View File

@@ -31,11 +31,7 @@ class Specifier extends Element, @specifier {
* A C/C++ function specifier: `inline`, `virtual`, or `explicit`. * A C/C++ function specifier: `inline`, `virtual`, or `explicit`.
*/ */
class FunctionSpecifier extends Specifier { class FunctionSpecifier extends Specifier {
FunctionSpecifier() { FunctionSpecifier() { this.hasName(["inline", "virtual", "explicit"]) }
this.hasName("inline") or
this.hasName("virtual") or
this.hasName("explicit")
}
override string getAPrimaryQlClass() { result = "FunctionSpecifier" } override string getAPrimaryQlClass() { result = "FunctionSpecifier" }
} }
@@ -45,13 +41,7 @@ class FunctionSpecifier extends Specifier {
* or `mutable". * or `mutable".
*/ */
class StorageClassSpecifier extends Specifier { class StorageClassSpecifier extends Specifier {
StorageClassSpecifier() { StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) }
this.hasName("auto") or
this.hasName("register") or
this.hasName("static") or
this.hasName("extern") or
this.hasName("mutable")
}
override string getAPrimaryQlClass() { result = "StorageClassSpecifier" } override string getAPrimaryQlClass() { result = "StorageClassSpecifier" }
} }
@@ -60,11 +50,7 @@ class StorageClassSpecifier extends Specifier {
* A C++ access specifier: `public`, `protected`, or `private`. * A C++ access specifier: `public`, `protected`, or `private`.
*/ */
class AccessSpecifier extends Specifier { class AccessSpecifier extends Specifier {
AccessSpecifier() { AccessSpecifier() { this.hasName(["public", "protected", "private"]) }
this.hasName("public") or
this.hasName("protected") or
this.hasName("private")
}
/** /**
* Gets the visibility of a field with access specifier `this` if it is * Gets the visibility of a field with access specifier `this` if it is
@@ -140,7 +126,7 @@ class Attribute extends Element, @attribute {
AttributeArgument getArgument(int i) { result.getAttribute() = this and result.getIndex() = i } AttributeArgument getArgument(int i) { result.getAttribute() = this and result.getIndex() = i }
/** Gets an argument of the attribute. */ /** Gets an argument of the attribute. */
AttributeArgument getAnArgument() { result = getArgument(_) } AttributeArgument getAnArgument() { result = this.getArgument(_) }
} }
/** /**
@@ -166,7 +152,7 @@ class StdAttribute extends Attribute, @stdattribute {
* Holds if this attribute has the given namespace and name. * Holds if this attribute has the given namespace and name.
*/ */
predicate hasQualifiedName(string namespace, string name) { predicate hasQualifiedName(string namespace, string name) {
namespace = getNamespace() and hasName(name) namespace = this.getNamespace() and this.hasName(name)
} }
} }
@@ -184,7 +170,7 @@ class Declspec extends Attribute, @declspec { }
*/ */
class MicrosoftAttribute extends Attribute, @msattribute { class MicrosoftAttribute extends Attribute, @msattribute {
AttributeArgument getNamedArgument(string name) { AttributeArgument getNamedArgument(string name) {
result = getAnArgument() and result.getName() = name result = this.getAnArgument() and result.getName() = name
} }
} }
@@ -212,13 +198,13 @@ class AlignAs extends Attribute, @alignas {
* ``` * ```
*/ */
class FormatAttribute extends GnuAttribute { class FormatAttribute extends GnuAttribute {
FormatAttribute() { getName() = "format" } FormatAttribute() { this.getName() = "format" }
/** /**
* Gets the archetype of this format attribute, for example * Gets the archetype of this format attribute, for example
* `"printf"`. * `"printf"`.
*/ */
string getArchetype() { result = getArgument(0).getValueText() } string getArchetype() { result = this.getArgument(0).getValueText() }
/** /**
* Gets the index in (1-based) format attribute notation associated * Gets the index in (1-based) format attribute notation associated
@@ -236,7 +222,7 @@ class FormatAttribute extends GnuAttribute {
* Gets the (0-based) index of the format string, * Gets the (0-based) index of the format string,
* according to this attribute. * according to this attribute.
*/ */
int getFormatIndex() { result = getArgument(1).getValueInt() - firstArgumentNumber() } int getFormatIndex() { result = this.getArgument(1).getValueInt() - this.firstArgumentNumber() }
/** /**
* Gets the (0-based) index of the first format argument (if any), * Gets the (0-based) index of the first format argument (if any),
@@ -244,8 +230,8 @@ class FormatAttribute extends GnuAttribute {
*/ */
int getFirstFormatArgIndex() { int getFirstFormatArgIndex() {
exists(int val | exists(int val |
val = getArgument(2).getValueInt() and val = this.getArgument(2).getValueInt() and
result = val - firstArgumentNumber() and result = val - this.firstArgumentNumber() and
not val = 0 // indicates a `vprintf` style format function with arguments not directly available. not val = 0 // indicates a `vprintf` style format function with arguments not directly available.
) )
} }
@@ -277,7 +263,7 @@ class AttributeArgument extends Element, @attribute_arg {
/** /**
* Gets the value of this argument, if its value is integral. * Gets the value of this argument, if its value is integral.
*/ */
int getValueInt() { result = getValueText().toInt() } int getValueInt() { result = this.getValueText().toInt() }
/** /**
* Gets the value of this argument, if its value is a type. * Gets the value of this argument, if its value is a type.
@@ -304,11 +290,11 @@ class AttributeArgument extends Element, @attribute_arg {
then result = "empty argument" then result = "empty argument"
else else
exists(string prefix, string tail | exists(string prefix, string tail |
(if exists(getName()) then prefix = getName() + "=" else prefix = "") and (if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and
( (
if exists(@attribute_arg_type self | self = underlyingElement(this)) if exists(@attribute_arg_type self | self = underlyingElement(this))
then tail = getValueType().getName() then tail = this.getValueType().getName()
else tail = getValueText() else tail = this.getValueText()
) and ) and
result = prefix + tail result = prefix + tail
) )

View File

@@ -41,7 +41,7 @@ class Struct extends Class {
* ``` * ```
*/ */
class LocalStruct extends Struct { class LocalStruct extends Struct {
LocalStruct() { isLocal() } LocalStruct() { this.isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" } override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" }
} }

View File

@@ -10,8 +10,8 @@ import semmle.code.cpp.File
*/ */
private class GoogleTestHeader extends File { private class GoogleTestHeader extends File {
GoogleTestHeader() { GoogleTestHeader() {
getBaseName() = "gtest.h" and this.getBaseName() = "gtest.h" and
getParentContainer().getBaseName() = "gtest" this.getParentContainer().getBaseName() = "gtest"
} }
} }
@@ -30,8 +30,8 @@ private class GoogleTest extends MacroInvocation {
*/ */
private class BoostTestFolder extends Folder { private class BoostTestFolder extends Folder {
BoostTestFolder() { BoostTestFolder() {
getBaseName() = "test" and this.getBaseName() = "test" and
getParentContainer().getBaseName() = "boost" this.getParentContainer().getBaseName() = "boost"
} }
} }
@@ -49,7 +49,7 @@ private class BoostTest extends MacroInvocation {
* The `cppunit` directory. * The `cppunit` directory.
*/ */
private class CppUnitFolder extends Folder { private class CppUnitFolder extends Folder {
CppUnitFolder() { getBaseName() = "cppunit" } CppUnitFolder() { this.getBaseName() = "cppunit" }
} }
/** /**
@@ -57,8 +57,8 @@ private class CppUnitFolder extends Folder {
*/ */
private class CppUnitClass extends Class { private class CppUnitClass extends Class {
CppUnitClass() { CppUnitClass() {
getFile().getParentContainer+() instanceof CppUnitFolder and this.getFile().getParentContainer+() instanceof CppUnitFolder and
getNamespace().getParentNamespace*().getName() = "CppUnit" this.getNamespace().getParentNamespace*().getName() = "CppUnit"
} }
} }

View File

@@ -81,7 +81,7 @@ class Type extends Locatable, @type {
* Holds if this type refers to type `t` (by default, * Holds if this type refers to type `t` (by default,
* a type always refers to itself). * a type always refers to itself).
*/ */
predicate refersTo(Type t) { refersToDirectly*(t) } predicate refersTo(Type t) { this.refersToDirectly*(t) }
/** /**
* Holds if this type refers to type `t` directly. * Holds if this type refers to type `t` directly.
@@ -1080,11 +1080,11 @@ class DerivedType extends Type, @derivedtype {
override predicate refersToDirectly(Type t) { t = this.getBaseType() } override predicate refersToDirectly(Type t) { t = this.getBaseType() }
override predicate involvesReference() { getBaseType().involvesReference() } override predicate involvesReference() { this.getBaseType().involvesReference() }
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override Type stripType() { result = getBaseType().stripType() } override Type stripType() { result = this.getBaseType().stripType() }
/** /**
* Holds if this type has the `__autoreleasing` specifier or if it points to * Holds if this type has the `__autoreleasing` specifier or if it points to
@@ -1165,33 +1165,35 @@ class Decltype extends Type, @decltype {
*/ */
predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) } predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) }
override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() } override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
override Type stripType() { result = getBaseType().stripType() } override Type stripType() { result = this.getBaseType().stripType() }
override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() } override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
override Location getLocation() { result = getExpr().getLocation() } override Location getLocation() { result = this.getExpr().getLocation() }
override string toString() { result = "decltype(...)" } override string toString() { result = "decltype(...)" }
override string getName() { none() } override string getName() { none() }
override int getSize() { result = getBaseType().getSize() } override int getSize() { result = this.getBaseType().getSize() }
override int getAlignment() { result = getBaseType().getAlignment() } override int getAlignment() { result = this.getBaseType().getAlignment() }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } override int getPointerIndirectionLevel() {
result = this.getBaseType().getPointerIndirectionLevel()
}
override string explain() { override string explain() {
result = "decltype resulting in {" + this.getBaseType().explain() + "}" result = "decltype resulting in {" + this.getBaseType().explain() + "}"
} }
override predicate involvesReference() { getBaseType().involvesReference() } override predicate involvesReference() { this.getBaseType().involvesReference() }
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() } override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() }
@@ -1223,7 +1225,7 @@ class PointerType extends DerivedType {
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
override Type resolveTypedefs() { override Type resolveTypedefs() {
result.(PointerType).getBaseType() = getBaseType().resolveTypedefs() result.(PointerType).getBaseType() = this.getBaseType().resolveTypedefs()
} }
} }
@@ -1240,7 +1242,9 @@ class ReferenceType extends DerivedType {
override string getAPrimaryQlClass() { result = "ReferenceType" } override string getAPrimaryQlClass() { result = "ReferenceType" }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } override int getPointerIndirectionLevel() {
result = this.getBaseType().getPointerIndirectionLevel()
}
override string explain() { result = "reference to {" + this.getBaseType().explain() + "}" } override string explain() { result = "reference to {" + this.getBaseType().explain() + "}" }
@@ -1251,7 +1255,7 @@ class ReferenceType extends DerivedType {
override predicate involvesReference() { any() } override predicate involvesReference() { any() }
override Type resolveTypedefs() { override Type resolveTypedefs() {
result.(ReferenceType).getBaseType() = getBaseType().resolveTypedefs() result.(ReferenceType).getBaseType() = this.getBaseType().resolveTypedefs()
} }
} }
@@ -1330,11 +1334,11 @@ class SpecifiedType extends DerivedType {
} }
override Type resolveTypedefs() { override Type resolveTypedefs() {
result.(SpecifiedType).getBaseType() = getBaseType().resolveTypedefs() and result.(SpecifiedType).getBaseType() = this.getBaseType().resolveTypedefs() and
result.getASpecifier() = getASpecifier() result.getASpecifier() = this.getASpecifier()
} }
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
} }
/** /**
@@ -1433,7 +1437,8 @@ class GNUVectorType extends DerivedType {
override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) } override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) }
override string explain() { override string explain() {
result = "GNU " + getNumElements() + " element vector of {" + this.getBaseType().explain() + "}" result =
"GNU " + this.getNumElements() + " element vector of {" + this.getBaseType().explain() + "}"
} }
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
@@ -1468,7 +1473,9 @@ class FunctionReferenceType extends FunctionPointerIshType {
override string getAPrimaryQlClass() { result = "FunctionReferenceType" } override string getAPrimaryQlClass() { result = "FunctionReferenceType" }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } override int getPointerIndirectionLevel() {
result = this.getBaseType().getPointerIndirectionLevel()
}
override string explain() { override string explain() {
result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}" result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}"
@@ -1535,8 +1542,8 @@ class FunctionPointerIshType extends DerivedType {
int getNumberOfParameters() { result = count(int i | exists(this.getParameterType(i))) } int getNumberOfParameters() { result = count(int i | exists(this.getParameterType(i))) }
override predicate involvesTemplateParameter() { override predicate involvesTemplateParameter() {
getReturnType().involvesTemplateParameter() or this.getReturnType().involvesTemplateParameter() or
getAParameterType().involvesTemplateParameter() this.getAParameterType().involvesTemplateParameter()
} }
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
@@ -1581,7 +1588,7 @@ class PointerToMemberType extends Type, @ptrtomember {
this.getBaseType().explain() + "}" this.getBaseType().explain() + "}"
} }
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
} }
@@ -1650,7 +1657,6 @@ class RoutineType extends Type, @routinetype {
i = 0 and result = "" and not exists(this.getAParameterType()) i = 0 and result = "" and not exists(this.getAParameterType())
or or
( (
exists(this.getParameterType(i)) and
if i < max(int j | exists(this.getParameterType(j))) if i < max(int j | exists(this.getParameterType(j)))
then then
// Not the last one // Not the last one
@@ -1671,8 +1677,8 @@ class RoutineType extends Type, @routinetype {
override predicate isDeeplyConstBelow() { none() } // Current limitation: no such thing as a const routine type override predicate isDeeplyConstBelow() { none() } // Current limitation: no such thing as a const routine type
override predicate involvesTemplateParameter() { override predicate involvesTemplateParameter() {
getReturnType().involvesTemplateParameter() or this.getReturnType().involvesTemplateParameter() or
getAParameterType().involvesTemplateParameter() this.getAParameterType().involvesTemplateParameter()
} }
} }

View File

@@ -25,7 +25,7 @@ class TypedefType extends UserType {
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() } override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
override int getSize() { result = this.getBaseType().getSize() } override int getSize() { result = this.getBaseType().getSize() }
@@ -43,11 +43,11 @@ class TypedefType extends UserType {
result = this.getBaseType().getASpecifier() result = this.getBaseType().getASpecifier()
} }
override predicate involvesReference() { getBaseType().involvesReference() } override predicate involvesReference() { this.getBaseType().involvesReference() }
override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() } override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
override Type stripType() { result = getBaseType().stripType() } override Type stripType() { result = this.getBaseType().stripType() }
} }
/** /**
@@ -90,7 +90,7 @@ class UsingAliasTypedefType extends TypedefType {
* ``` * ```
*/ */
class LocalTypedefType extends TypedefType { class LocalTypedefType extends TypedefType {
LocalTypedefType() { isLocal() } LocalTypedefType() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalTypedefType" } override string getAPrimaryQlClass() { result = "LocalTypedefType" }
} }

View File

@@ -37,7 +37,7 @@ class Union extends Struct {
* ``` * ```
*/ */
class LocalUnion extends Union { class LocalUnion extends Union {
LocalUnion() { isLocal() } LocalUnion() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalUnion" } override string getAPrimaryQlClass() { result = "LocalUnion" }
} }

View File

@@ -30,19 +30,19 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* Gets the simple name of this type, without any template parameters. For example * Gets the simple name of this type, without any template parameters. For example
* if the name of the type is `"myType<int>"`, the simple name is just `"myType"`. * if the name of the type is `"myType<int>"`, the simple name is just `"myType"`.
*/ */
string getSimpleName() { result = getName().regexpReplaceAll("<.*", "") } string getSimpleName() { result = this.getName().regexpReplaceAll("<.*", "") }
override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) } override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) }
/** Holds if this type is anonymous. */ /** Holds if this type is anonymous. */
predicate isAnonymous() { getName().matches("(unnamed%") } predicate isAnonymous() { this.getName().matches("(unnamed%") }
override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) } override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) }
override Specifier getASpecifier() { result = Type.super.getASpecifier() } override Specifier getASpecifier() { result = Type.super.getASpecifier() }
override Location getLocation() { override Location getLocation() {
if hasDefinition() if this.hasDefinition()
then result = this.getDefinitionLocation() then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation() else result = this.getADeclarationLocation()
} }
@@ -53,16 +53,16 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry()) else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
} }
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
override TypeDeclarationEntry getDefinition() { override TypeDeclarationEntry getDefinition() {
result = getADeclarationEntry() and result = this.getADeclarationEntry() and
result.isDefinition() result.isDefinition()
} }
override Location getDefinitionLocation() { override Location getDefinitionLocation() {
if exists(getDefinition()) if exists(this.getDefinition())
then result = getDefinition().getLocation() then result = this.getDefinition().getLocation()
else else
exists(Class t | exists(Class t |
this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation() this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation()
@@ -80,7 +80,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* Holds if this is a local type (that is, a type that has a directly-enclosing * Holds if this is a local type (that is, a type that has a directly-enclosing
* function). * function).
*/ */
predicate isLocal() { exists(getEnclosingFunction()) } predicate isLocal() { exists(this.getEnclosingFunction()) }
/* /*
* Dummy implementations of inherited methods. This class must not be * Dummy implementations of inherited methods. This class must not be
@@ -107,9 +107,9 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* ``` * ```
*/ */
class TypeDeclarationEntry extends DeclarationEntry, @type_decl { class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
override UserType getDeclaration() { result = getType() } override UserType getDeclaration() { result = this.getType() }
override string getName() { result = getType().getName() } override string getName() { result = this.getType().getName() }
override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" } override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" }

View File

@@ -104,17 +104,17 @@ class Variable extends Declaration, @variable {
override VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this } override VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this }
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
override VariableDeclarationEntry getDefinition() { override VariableDeclarationEntry getDefinition() {
result = getADeclarationEntry() and result = this.getADeclarationEntry() and
result.isDefinition() result.isDefinition()
} }
override Location getDefinitionLocation() { result = getDefinition().getLocation() } override Location getDefinitionLocation() { result = this.getDefinition().getLocation() }
override Location getLocation() { override Location getLocation() {
if exists(getDefinition()) if exists(this.getDefinition())
then result = this.getDefinitionLocation() then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation() else result = this.getADeclarationLocation()
} }
@@ -199,7 +199,7 @@ class Variable extends Declaration, @variable {
* ``` * ```
*/ */
class VariableDeclarationEntry extends DeclarationEntry, @var_decl { class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
override Variable getDeclaration() { result = getVariable() } override Variable getDeclaration() { result = this.getVariable() }
override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" } override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" }
@@ -276,32 +276,33 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
int getIndex() { param_decl_bind(underlyingElement(this), result, _) } int getIndex() { param_decl_bind(underlyingElement(this), result, _) }
private string getAnonymousParameterDescription() { private string getAnonymousParameterDescription() {
not exists(getName()) and not exists(this.getName()) and
exists(string idx | exists(string idx |
idx = idx =
((getIndex() + 1).toString() + "th") ((this.getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st") .replaceAll("1th", "1st")
.replaceAll("2th", "2nd") .replaceAll("2th", "2nd")
.replaceAll("3th", "3rd") .replaceAll("3th", "3rd")
.replaceAll("11st", "11th") .replaceAll("11st", "11th")
.replaceAll("12nd", "12th") .replaceAll("12nd", "12th")
.replaceAll("13rd", "13th") and .replaceAll("13rd", "13th") and
if exists(getCanonicalName()) if exists(this.getCanonicalName())
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter" then
result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter"
else result = "declaration of " + idx + " parameter" else result = "declaration of " + idx + " parameter"
) )
} }
override string toString() { override string toString() {
isDefinition() and this.isDefinition() and
result = "definition of " + getName() result = "definition of " + this.getName()
or or
not isDefinition() and not this.isDefinition() and
if getName() = getCanonicalName() if this.getName() = this.getCanonicalName()
then result = "declaration of " + getName() then result = "declaration of " + this.getName()
else result = "declaration of " + getCanonicalName() + " as " + getName() else result = "declaration of " + this.getCanonicalName() + " as " + this.getName()
or or
result = getAnonymousParameterDescription() result = this.getAnonymousParameterDescription()
} }
/** /**
@@ -311,8 +312,12 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
*/ */
string getTypedName() { string getTypedName() {
exists(string typeString, string nameString | exists(string typeString, string nameString |
(if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and (
(if exists(getName()) then nameString = getName() else nameString = "") and if exists(this.getType().getName())
then typeString = this.getType().getName()
else typeString = ""
) and
(if exists(this.getName()) then nameString = this.getName() else nameString = "") and
if typeString != "" and nameString != "" if typeString != "" and nameString != ""
then result = typeString + " " + nameString then result = typeString + " " + nameString
else result = typeString + nameString else result = typeString + nameString
@@ -540,7 +545,7 @@ class MemberVariable extends Variable, @membervariable {
} }
/** Holds if this member is mutable. */ /** Holds if this member is mutable. */
predicate isMutable() { getADeclarationEntry().hasSpecifier("mutable") } predicate isMutable() { this.getADeclarationEntry().hasSpecifier("mutable") }
private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) } private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) }
} }

View File

@@ -24,7 +24,7 @@ class XMLLocatable extends @xmllocatable, TXMLLocatable {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
} }
/** Gets the text value contained in this XML parent. */ /** Gets the text value contained in this XML parent. */
string getTextValue() { result = allCharactersString() } string getTextValue() { result = this.allCharactersString() }
/** Gets a printable representation of this XML parent. */ /** Gets a printable representation of this XML parent. */
string toString() { result = this.getName() } string toString() { result = this.getName() }
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
XMLFile() { xmlEncoding(this, _) } XMLFile() { xmlEncoding(this, _) }
/** Gets a printable representation of this XML file. */ /** Gets a printable representation of this XML file. */
override string toString() { result = getName() } override string toString() { result = this.getName() }
/** Gets the name of this XML file. */ /** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() } override string getName() { result = File.super.getAbsolutePath() }
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
* *
* Gets the path of this XML file. * Gets the path of this XML file.
*/ */
deprecated string getPath() { result = getAbsolutePath() } deprecated string getPath() { result = this.getAbsolutePath() }
/** /**
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
* *
* Gets the path of the folder that contains this XML file. * Gets the path of the folder that contains this XML file.
*/ */
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() } deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
/** Gets the encoding of this XML file. */ /** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this, result) } string getEncoding() { xmlEncoding(this, result) }
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
*/ */
class XMLElement extends @xmlelement, XMLParent, XMLLocatable { class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
/** Holds if this XML element has the given `name`. */ /** Holds if this XML element has the given `name`. */
predicate hasName(string name) { name = getName() } predicate hasName(string name) { name = this.getName() }
/** Gets the name of this XML element. */ /** Gets the name of this XML element. */
override string getName() { xmlElements(this, result, _, _, _) } override string getName() { xmlElements(this, result, _, _, _) }
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
/** Gets a printable representation of this XML element. */ /** Gets a printable representation of this XML element. */
override string toString() { result = getName() } override string toString() { result = this.getName() }
} }
/** /**

View File

@@ -10,44 +10,11 @@ import semmle.code.cpp.dataflow.DataFlow
* char data[1]; // v * char data[1]; // v
* }; * };
* ``` * ```
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. * This requires that `v` is an array of size 0 or 1.
* In addition, if the size of the structure is taken, there must be at least one instance
* where a `c` pointer is allocated with additional space.
* For example, holds for `c` if it occurs as
* ```
* malloc(sizeof(c) + 100 * sizeof(char))
* ```
* but not if it only ever occurs as
* ```
* malloc(sizeof(c))
* ```
*/ */
predicate memberMayBeVarSize(Class c, MemberVariable v) { predicate memberMayBeVarSize(Class c, MemberVariable v) {
exists(int i | c = v.getDeclaringType() and
// `v` is the last field in `c` v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
v = c.getCanonicalMember(i) and
// v is an array of size at most 1
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
not c instanceof Union
) and
// If the size is taken, then arithmetic is performed on the result at least once
(
// `sizeof(c)` is not taken
not exists(SizeofOperator so |
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
)
or
// or `sizeof(c)` is taken
exists(SizeofOperator so |
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
// and arithmetic is performed on the result
so.getParent*() instanceof AddExpr
)
)
} }
/** /**
@@ -60,10 +27,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
why = bufferVar and why = bufferVar and
not memberMayBeVarSize(_, bufferVar) and not memberMayBeVarSize(_, bufferVar) and
not exists(Union bufferType |
bufferType.getAMemberVariable() = why and
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
) and
not result = 0 // zero sized arrays are likely to have special usage, for example not result = 0 // zero sized arrays are likely to have special usage, for example
or or
// behaving a bit like a 'union' overlapping other fields. // behaving a bit like a 'union' overlapping other fields.
@@ -85,13 +48,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize() result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
) )
or
exists(Union bufferType |
bufferType.getAMemberVariable() = why and
why = bufferVar and
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1 and
result = bufferType.getSize()
)
) )
or or
// buffer is a fixed size dynamic allocation // buffer is a fixed size dynamic allocation

View File

@@ -375,8 +375,8 @@ class Wchar_t extends Type {
class MicrosoftInt8Type extends IntegralType { class MicrosoftInt8Type extends IntegralType {
MicrosoftInt8Type() { MicrosoftInt8Type() {
this instanceof CharType and this instanceof CharType and
not isExplicitlyUnsigned() and not this.isExplicitlyUnsigned() and
not isExplicitlySigned() not this.isExplicitlySigned()
} }
} }
@@ -391,8 +391,8 @@ class MicrosoftInt8Type extends IntegralType {
class MicrosoftInt16Type extends IntegralType { class MicrosoftInt16Type extends IntegralType {
MicrosoftInt16Type() { MicrosoftInt16Type() {
this instanceof ShortType and this instanceof ShortType and
not isExplicitlyUnsigned() and not this.isExplicitlyUnsigned() and
not isExplicitlySigned() not this.isExplicitlySigned()
} }
} }
@@ -407,8 +407,8 @@ class MicrosoftInt16Type extends IntegralType {
class MicrosoftInt32Type extends IntegralType { class MicrosoftInt32Type extends IntegralType {
MicrosoftInt32Type() { MicrosoftInt32Type() {
this instanceof IntType and this instanceof IntType and
not isExplicitlyUnsigned() and not this.isExplicitlyUnsigned() and
not isExplicitlySigned() not this.isExplicitlySigned()
} }
} }
@@ -423,8 +423,8 @@ class MicrosoftInt32Type extends IntegralType {
class MicrosoftInt64Type extends IntegralType { class MicrosoftInt64Type extends IntegralType {
MicrosoftInt64Type() { MicrosoftInt64Type() {
this instanceof LongLongType and this instanceof LongLongType and
not isExplicitlyUnsigned() and not this.isExplicitlyUnsigned() and
not isExplicitlySigned() not this.isExplicitlySigned()
} }
} }

View File

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

View File

@@ -1,6 +1,7 @@
import cpp import cpp
private import semmle.code.cpp.models.interfaces.ArrayFunction private import semmle.code.cpp.models.interfaces.ArrayFunction
private import semmle.code.cpp.models.implementations.Strcat private import semmle.code.cpp.models.implementations.Strcat
import semmle.code.cpp.dataflow.DataFlow
private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) { private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) {
exists(StackVariable v0, Expr val | exists(StackVariable v0, Expr val |
@@ -45,22 +46,28 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) {
ae.getRValue().getAChild*() = va ae.getRValue().getAChild*() = va
) )
or or
// Function call: library function, varargs function, function // Function calls...
// containing assembler code, or function where the relevant
// parameter is potentially added a null terminator.
exists(Call c, Function f, int i | exists(Call c, Function f, int i |
e = c and e = c and
f = c.getTarget() and f = c.getTarget() and
not functionArgumentMustBeNullTerminated(f, i) and not functionArgumentMustBeNullTerminated(f, i) and
c.getAnArgumentSubExpr(i) = va c.getAnArgumentSubExpr(i) = va
| |
not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i) // library function
not f.hasEntryPoint()
or or
// function where the relevant parameter is potentially added a null terminator
mayAddNullTerminator(_, f.getParameter(i).getAnAccess()) mayAddNullTerminator(_, f.getParameter(i).getAnAccess())
or or
// varargs function
f.isVarargs() and i >= f.getNumberOfParameters() f.isVarargs() and i >= f.getNumberOfParameters()
or or
// function containing assembler code
exists(AsmStmt s | s.getEnclosingFunction() = f) exists(AsmStmt s | s.getEnclosingFunction() = f)
or
// function where the relevant parameter is returned (leaking it to be potentially null terminated elsewhere)
DataFlow::localFlow(DataFlow::parameterNode(f.getParameter(i)),
DataFlow::exprNode(any(ReturnStmt rs).getExpr()))
) )
or or
// Call without target (e.g., function pointer call) // Call without target (e.g., function pointer call)
@@ -93,6 +100,15 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
fc.getArgument(i) = va fc.getArgument(i) = va
) )
or or
// String argument to a formatting function (such as `printf`)
exists(int n, FormatLiteral fl |
fc.(FormattingFunctionCall).getConversionArgument(n) = va and
fl = fc.(FormattingFunctionCall).getFormat() and
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
not fl.hasPrecision(n) // exclude: `%.*s`
)
or
// Call to a wrapper function that requires null termination // Call to a wrapper function that requires null termination
// (not itself adding a null terminator) // (not itself adding a null terminator)
exists(Function wrapper, int i, Parameter p, VariableAccess use | exists(Function wrapper, int i, Parameter p, VariableAccess use |

View File

@@ -8,7 +8,7 @@ import semmle.code.cpp.commons.StringAnalysis
import semmle.code.cpp.models.interfaces.FormattingFunction import semmle.code.cpp.models.interfaces.FormattingFunction
class PrintfFormatAttribute extends FormatAttribute { class PrintfFormatAttribute extends FormatAttribute {
PrintfFormatAttribute() { getArchetype() = ["printf", "__printf__"] } PrintfFormatAttribute() { this.getArchetype() = ["printf", "__printf__"] }
} }
/** /**
@@ -20,13 +20,13 @@ class AttributeFormattingFunction extends FormattingFunction {
AttributeFormattingFunction() { AttributeFormattingFunction() {
exists(PrintfFormatAttribute printf_attrib | exists(PrintfFormatAttribute printf_attrib |
printf_attrib = getAnAttribute() and printf_attrib = this.getAnAttribute() and
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
) )
} }
override int getFormatParameterIndex() { override int getFormatParameterIndex() {
forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() | forex(PrintfFormatAttribute printf_attrib | printf_attrib = this.getAnAttribute() |
result = printf_attrib.getFormatIndex() result = printf_attrib.getFormatIndex()
) )
} }
@@ -132,7 +132,7 @@ deprecated predicate variadicFormatter(Function f, int formatParamIndex) {
class UserDefinedFormattingFunction extends FormattingFunction { class UserDefinedFormattingFunction extends FormattingFunction {
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" } override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _, _, _) } UserDefinedFormattingFunction() { this.isVarargs() and callsVariadicFormatter(this, _, _, _) }
override int getFormatParameterIndex() { callsVariadicFormatter(this, _, result, _) } override int getFormatParameterIndex() { callsVariadicFormatter(this, _, result, _) }
@@ -191,7 +191,7 @@ class FormattingFunctionCall extends Expr {
exists(int i | exists(int i |
result = this.getArgument(i) and result = this.getArgument(i) and
n >= 0 and n >= 0 and
n = i - getTarget().(FormattingFunction).getFirstFormatArgumentIndex() n = i - this.getTarget().(FormattingFunction).getFirstFormatArgumentIndex()
) )
} }
@@ -251,7 +251,22 @@ class FormattingFunctionCall extends Expr {
int getNumFormatArgument() { int getNumFormatArgument() {
result = count(this.getFormatArgument(_)) and result = count(this.getFormatArgument(_)) and
// format arguments must be known // format arguments must be known
exists(getTarget().(FormattingFunction).getFirstFormatArgumentIndex()) exists(this.getTarget().(FormattingFunction).getFirstFormatArgumentIndex())
}
/**
* Gets the argument, if any, to which the output is written. If `isStream` is
* `true`, the output argument is a stream (that is, this call behaves like
* `fprintf`). If `isStream` is `false`, the output argument is a buffer (that
* is, this call behaves like `sprintf`)
*/
Expr getOutputArgument(boolean isStream) {
result =
this.(Call)
.getArgument(this.(Call)
.getTarget()
.(FormattingFunction)
.getOutputParameterIndex(isStream))
} }
} }
@@ -275,7 +290,7 @@ class FormatLiteral extends Literal {
* DEPRECATED: Use getDefaultCharType() instead. * DEPRECATED: Use getDefaultCharType() instead.
*/ */
deprecated predicate isWideCharDefault() { deprecated predicate isWideCharDefault() {
getUse().getTarget().(FormattingFunction).isWideCharDefault() this.getUse().getTarget().(FormattingFunction).isWideCharDefault()
} }
/** /**
@@ -283,7 +298,7 @@ class FormatLiteral extends Literal {
* `char` or `wchar_t`. * `char` or `wchar_t`.
*/ */
Type getDefaultCharType() { Type getDefaultCharType() {
result = getUse().getTarget().(FormattingFunction).getDefaultCharType() result = this.getUse().getTarget().(FormattingFunction).getDefaultCharType()
} }
/** /**
@@ -292,7 +307,7 @@ class FormatLiteral extends Literal {
* which is correct for a particular function. * which is correct for a particular function.
*/ */
Type getNonDefaultCharType() { Type getNonDefaultCharType() {
result = getUse().getTarget().(FormattingFunction).getNonDefaultCharType() result = this.getUse().getTarget().(FormattingFunction).getNonDefaultCharType()
} }
/** /**
@@ -300,7 +315,9 @@ class FormatLiteral extends Literal {
* snapshots there may be multiple results where we can't tell which is correct for a * snapshots there may be multiple results where we can't tell which is correct for a
* particular function. * particular function.
*/ */
Type getWideCharType() { result = getUse().getTarget().(FormattingFunction).getWideCharType() } Type getWideCharType() {
result = this.getUse().getTarget().(FormattingFunction).getWideCharType()
}
/** /**
* Holds if this `FormatLiteral` is in a context that supports * Holds if this `FormatLiteral` is in a context that supports
@@ -338,7 +355,7 @@ class FormatLiteral extends Literal {
} }
private string getFlagRegexp() { private string getFlagRegexp() {
if isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*" if this.isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*"
} }
private string getFieldWidthRegexp() { result = "(?:[1-9][0-9]*|\\*|\\*[0-9]+\\$)?" } private string getFieldWidthRegexp() { result = "(?:[1-9][0-9]*|\\*|\\*[0-9]+\\$)?" }
@@ -346,13 +363,13 @@ class FormatLiteral extends Literal {
private string getPrecRegexp() { result = "(?:\\.(?:[0-9]*|\\*|\\*[0-9]+\\$))?" } private string getPrecRegexp() { result = "(?:\\.(?:[0-9]*|\\*|\\*[0-9]+\\$))?" }
private string getLengthRegexp() { private string getLengthRegexp() {
if isMicrosoft() if this.isMicrosoft()
then result = "(?:hh?|ll?|L|q|j|z|t|w|I32|I64|I)?" then result = "(?:hh?|ll?|L|q|j|z|t|w|I32|I64|I)?"
else result = "(?:hh?|ll?|L|q|j|z|Z|t)?" else result = "(?:hh?|ll?|L|q|j|z|Z|t)?"
} }
private string getConvCharRegexp() { private string getConvCharRegexp() {
if isMicrosoft() if this.isMicrosoft()
then result = "[aAcCdeEfFgGimnopsSuxXZ@]" then result = "[aAcCdeEfFgGimnopsSuxXZ@]"
else result = "[aAcCdeEfFgGimnopsSuxX@]" else result = "[aAcCdeEfFgGimnopsSuxX@]"
} }
@@ -732,16 +749,16 @@ class FormatLiteral extends Literal {
* Gets the argument type required by the nth conversion specifier. * Gets the argument type required by the nth conversion specifier.
*/ */
Type getConversionType(int n) { Type getConversionType(int n) {
result = getConversionType1(n) or result = this.getConversionType1(n) or
result = getConversionType1b(n) or result = this.getConversionType1b(n) or
result = getConversionType2(n) or result = this.getConversionType2(n) or
result = getConversionType3(n) or result = this.getConversionType3(n) or
result = getConversionType4(n) or result = this.getConversionType4(n) or
result = getConversionType6(n) or result = this.getConversionType6(n) or
result = getConversionType7(n) or result = this.getConversionType7(n) or
result = getConversionType8(n) or result = this.getConversionType8(n) or
result = getConversionType9(n) or result = this.getConversionType9(n) or
result = getConversionType10(n) result = this.getConversionType10(n)
} }
private Type getConversionType1(int n) { private Type getConversionType1(int n) {
@@ -771,15 +788,15 @@ class FormatLiteral extends Literal {
or or
conv = ["c", "C"] and conv = ["c", "C"] and
len = ["l", "w"] and len = ["l", "w"] and
result = getWideCharType() result = this.getWideCharType()
or or
conv = "c" and conv = "c" and
(len != "l" and len != "w" and len != "h") and (len != "l" and len != "w" and len != "h") and
result = getDefaultCharType() result = this.getDefaultCharType()
or or
conv = "C" and conv = "C" and
(len != "l" and len != "w" and len != "h") and (len != "l" and len != "w" and len != "h") and
result = getNonDefaultCharType() result = this.getNonDefaultCharType()
) )
) )
} }
@@ -816,15 +833,15 @@ class FormatLiteral extends Literal {
or or
conv = ["s", "S"] and conv = ["s", "S"] and
len = ["l", "w"] and len = ["l", "w"] and
result.(PointerType).getBaseType() = getWideCharType() result.(PointerType).getBaseType() = this.getWideCharType()
or or
conv = "s" and conv = "s" and
(len != "l" and len != "w" and len != "h") and (len != "l" and len != "w" and len != "h") and
result.(PointerType).getBaseType() = getDefaultCharType() result.(PointerType).getBaseType() = this.getDefaultCharType()
or or
conv = "S" and conv = "S" and
(len != "l" and len != "w" and len != "h") and (len != "l" and len != "w" and len != "h") and
result.(PointerType).getBaseType() = getNonDefaultCharType() result.(PointerType).getBaseType() = this.getNonDefaultCharType()
) )
) )
} }
@@ -879,19 +896,19 @@ class FormatLiteral extends Literal {
exists(string len, string conv | exists(string len, string conv |
this.parseConvSpec(n, _, _, _, _, _, len, conv) and this.parseConvSpec(n, _, _, _, _, _, len, conv) and
(len != "l" and len != "w" and len != "h") and (len != "l" and len != "w" and len != "h") and
getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function this.getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function
( (
conv = "c" and conv = "c" and
result = getNonDefaultCharType() result = this.getNonDefaultCharType()
or or
conv = "C" and conv = "C" and
result = getDefaultCharType() result = this.getDefaultCharType()
or or
conv = "s" and conv = "s" and
result.(PointerType).getBaseType() = getNonDefaultCharType() result.(PointerType).getBaseType() = this.getNonDefaultCharType()
or or
conv = "S" and conv = "S" and
result.(PointerType).getBaseType() = getDefaultCharType() result.(PointerType).getBaseType() = this.getDefaultCharType()
) )
) )
} }
@@ -924,9 +941,13 @@ class FormatLiteral extends Literal {
* not account for positional arguments (`$`). * not account for positional arguments (`$`).
*/ */
int getFormatArgumentIndexFor(int n, int mode) { int getFormatArgumentIndexFor(int n, int mode) {
hasFormatArgumentIndexFor(n, mode) and this.hasFormatArgumentIndexFor(n, mode) and
(3 * n) + mode = (3 * n) + mode =
rank[result + 1](int n2, int mode2 | hasFormatArgumentIndexFor(n2, mode2) | (3 * n2) + mode2) rank[result + 1](int n2, int mode2 |
this.hasFormatArgumentIndexFor(n2, mode2)
|
(3 * n2) + mode2
)
} }
/** /**
@@ -936,7 +957,7 @@ class FormatLiteral extends Literal {
int getNumArgNeeded(int n) { int getNumArgNeeded(int n) {
exists(this.getConvSpecOffset(n)) and exists(this.getConvSpecOffset(n)) and
exists(this.getConversionChar(n)) and exists(this.getConversionChar(n)) and
result = count(int mode | hasFormatArgumentIndexFor(n, mode)) result = count(int mode | this.hasFormatArgumentIndexFor(n, mode))
} }
/** /**
@@ -948,7 +969,7 @@ class FormatLiteral extends Literal {
// At least one conversion specifier has a parameter field, in which case, // At least one conversion specifier has a parameter field, in which case,
// they all should have. // they all should have.
result = max(string s | this.getParameterField(_) = s + "$" | s.toInt()) result = max(string s | this.getParameterField(_) = s + "$" | s.toInt())
else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode)) else result = count(int n, int mode | this.hasFormatArgumentIndexFor(n, mode))
} }
/** /**
@@ -1038,10 +1059,10 @@ class FormatLiteral extends Literal {
exists(int sizeBits | exists(int sizeBits |
sizeBits = sizeBits =
min(int bits | min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8 bits = this.getIntegralDisplayType(n).getSize() * 8
or or
exists(IntegralType t | exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType() t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
| |
t.isSigned() and bits = t.getSize() * 8 t.isSigned() and bits = t.getSize() * 8
) )
@@ -1056,10 +1077,10 @@ class FormatLiteral extends Literal {
exists(int sizeBits | exists(int sizeBits |
sizeBits = sizeBits =
min(int bits | min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8 bits = this.getIntegralDisplayType(n).getSize() * 8
or or
exists(IntegralType t | exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType() t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
| |
t.isUnsigned() and bits = t.getSize() * 8 t.isUnsigned() and bits = t.getSize() * 8
) )
@@ -1074,26 +1095,26 @@ class FormatLiteral extends Literal {
exists(int sizeBytes, int baseLen | exists(int sizeBytes, int baseLen |
sizeBytes = sizeBytes =
min(int bytes | min(int bytes |
bytes = getIntegralDisplayType(n).getSize() bytes = this.getIntegralDisplayType(n).getSize()
or or
exists(IntegralType t | exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType() t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
| |
t.isUnsigned() and bytes = t.getSize() t.isUnsigned() and bytes = t.getSize()
) )
) and ) and
baseLen = sizeBytes * 2 and baseLen = sizeBytes * 2 and
( (
if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x" if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
) )
) )
or or
this.getConversionChar(n).toLowerCase() = "p" and this.getConversionChar(n).toLowerCase() = "p" and
exists(PointerType ptrType, int baseLen | exists(PointerType ptrType, int baseLen |
ptrType = getFullyConverted().getType() and ptrType = this.getFullyConverted().getType() and
baseLen = max(ptrType.getSize() * 2) and // e.g. "0x1234567812345678"; exact format is platform dependent baseLen = max(ptrType.getSize() * 2) and // e.g. "0x1234567812345678"; exact format is platform dependent
( (
if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x" if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
) )
) )
or or
@@ -1102,17 +1123,17 @@ class FormatLiteral extends Literal {
exists(int sizeBits, int baseLen | exists(int sizeBits, int baseLen |
sizeBits = sizeBits =
min(int bits | min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8 bits = this.getIntegralDisplayType(n).getSize() * 8
or or
exists(IntegralType t | exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType() t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
| |
t.isUnsigned() and bits = t.getSize() * 8 t.isUnsigned() and bits = t.getSize() * 8
) )
) and ) and
baseLen = (sizeBits / 3.0).ceil() and baseLen = (sizeBits / 3.0).ceil() and
( (
if hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0" if this.hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0"
) )
) )
or or
@@ -1135,8 +1156,8 @@ class FormatLiteral extends Literal {
*/ */
int getMaxConvertedLengthLimited(int n) { int getMaxConvertedLengthLimited(int n) {
if this.getConversionChar(n).toLowerCase() = "f" if this.getConversionChar(n).toLowerCase() = "f"
then result = getMaxConvertedLength(n).minimum(8) then result = this.getMaxConvertedLength(n).minimum(8)
else result = getMaxConvertedLength(n) else result = this.getMaxConvertedLength(n)
} }
/** /**

View File

@@ -24,7 +24,7 @@ abstract class ScanfFunction extends Function {
* Holds if the default meaning of `%s` is a `wchar_t*` string * Holds if the default meaning of `%s` is a `wchar_t*` string
* (rather than a `char*`). * (rather than a `char*`).
*/ */
predicate isWideCharDefault() { exists(getName().indexOf("wscanf")) } predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) }
} }
/** /**
@@ -34,10 +34,10 @@ class Scanf extends ScanfFunction {
Scanf() { Scanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...) this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...) this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...) this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...) this.hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
) )
} }
@@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction {
Fscanf() { Fscanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...) this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...) this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) this.hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
) )
} }
@@ -72,10 +72,10 @@ class Sscanf extends ScanfFunction {
Sscanf() { Sscanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...) this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...) this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...) this.hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
) )
} }
@@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction {
Snscanf() { Snscanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...) this.hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...) this.hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...) this.hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...) this.hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
// note that the max_amount is not a limit on the output length, it's an input length // note that the max_amount is not a limit on the output length, it's an input length
// limit used with non null-terminated strings. // limit used with non null-terminated strings.
) )
@@ -120,18 +120,18 @@ class ScanfFunctionCall extends FunctionCall {
/** /**
* Gets the `scanf`-like function that is called. * Gets the `scanf`-like function that is called.
*/ */
ScanfFunction getScanfFunction() { result = getTarget() } ScanfFunction getScanfFunction() { result = this.getTarget() }
/** /**
* Gets the position at which the input string or stream parameter occurs, * Gets the position at which the input string or stream parameter occurs,
* if this function call does not read from standard input. * if this function call does not read from standard input.
*/ */
int getInputParameterIndex() { result = getScanfFunction().getInputParameterIndex() } int getInputParameterIndex() { result = this.getScanfFunction().getInputParameterIndex() }
/** /**
* Gets the position at which the format parameter occurs. * Gets the position at which the format parameter occurs.
*/ */
int getFormatParameterIndex() { result = getScanfFunction().getFormatParameterIndex() } int getFormatParameterIndex() { result = this.getScanfFunction().getFormatParameterIndex() }
/** /**
* Gets the format expression used in this call. * Gets the format expression used in this call.
@@ -142,7 +142,7 @@ class ScanfFunctionCall extends FunctionCall {
* Holds if the default meaning of `%s` is a `wchar_t*` string * Holds if the default meaning of `%s` is a `wchar_t*` string
* (rather than a `char*`). * (rather than a `char*`).
*/ */
predicate isWideCharDefault() { getScanfFunction().isWideCharDefault() } predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
} }
/** /**
@@ -158,7 +158,7 @@ class ScanfFormatLiteral extends Expr {
ScanfFunctionCall getUse() { result.getFormat() = this } ScanfFunctionCall getUse() { result.getFormat() = this }
/** Holds if the default meaning of `%s` is a `wchar_t*` (rather than a `char*`). */ /** Holds if the default meaning of `%s` is a `wchar_t*` (rather than a `char*`). */
predicate isWideCharDefault() { getUse().getTarget().(ScanfFunction).isWideCharDefault() } predicate isWideCharDefault() { this.getUse().getTarget().(ScanfFunction).isWideCharDefault() }
/** /**
* Gets the format string itself, transformed as follows: * Gets the format string itself, transformed as follows:

View File

@@ -40,8 +40,8 @@ abstract class MutexType extends Type {
* Gets a call that locks or tries to lock any mutex of this type. * Gets a call that locks or tries to lock any mutex of this type.
*/ */
FunctionCall getLockAccess() { FunctionCall getLockAccess() {
result = getMustlockAccess() or result = this.getMustlockAccess() or
result = getTrylockAccess() result = this.getTrylockAccess()
} }
/** /**
@@ -63,22 +63,22 @@ abstract class MutexType extends Type {
/** /**
* DEPRECATED: use mustlockAccess(fc, arg) instead. * DEPRECATED: use mustlockAccess(fc, arg) instead.
*/ */
deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() } deprecated Function getMustlockFunction() { result = this.getMustlockAccess().getTarget() }
/** /**
* DEPRECATED: use trylockAccess(fc, arg) instead. * DEPRECATED: use trylockAccess(fc, arg) instead.
*/ */
deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() } deprecated Function getTrylockFunction() { result = this.getTrylockAccess().getTarget() }
/** /**
* DEPRECATED: use lockAccess(fc, arg) instead. * DEPRECATED: use lockAccess(fc, arg) instead.
*/ */
deprecated Function getLockFunction() { result = getLockAccess().getTarget() } deprecated Function getLockFunction() { result = this.getLockAccess().getTarget() }
/** /**
* DEPRECATED: use unlockAccess(fc, arg) instead. * DEPRECATED: use unlockAccess(fc, arg) instead.
*/ */
deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() } deprecated Function getUnlockFunction() { result = this.getUnlockAccess().getTarget() }
} }
/** /**
@@ -155,17 +155,17 @@ class DefaultMutexType extends MutexType {
override predicate mustlockAccess(FunctionCall fc, Expr arg) { override predicate mustlockAccess(FunctionCall fc, Expr arg) {
fc.getTarget() = mustlockCandidate() and fc.getTarget() = mustlockCandidate() and
lockArgType(fc, arg) this.lockArgType(fc, arg)
} }
override predicate trylockAccess(FunctionCall fc, Expr arg) { override predicate trylockAccess(FunctionCall fc, Expr arg) {
fc.getTarget() = trylockCandidate() and fc.getTarget() = trylockCandidate() and
lockArgType(fc, arg) this.lockArgType(fc, arg)
} }
override predicate unlockAccess(FunctionCall fc, Expr arg) { override predicate unlockAccess(FunctionCall fc, Expr arg) {
fc.getTarget() = unlockCandidate() and fc.getTarget() = unlockCandidate() and
lockArgType(fc, arg) this.lockArgType(fc, arg)
} }
} }

View File

@@ -194,14 +194,14 @@ class BasicBlock extends ControlFlowNodeBase {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
* *
* Yields no result if this basic block spans multiple source files. * Yields no result if this basic block spans multiple source files.
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn) this.hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn)
} }
pragma[noinline] pragma[noinline]
@@ -276,7 +276,7 @@ class EntryBasicBlock extends BasicBlock {
*/ */
class ExitBasicBlock extends BasicBlock { class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { ExitBasicBlock() {
getEnd() instanceof Function or this.getEnd() instanceof Function or
aborting(getEnd()) aborting(this.getEnd())
} }
} }

View File

@@ -66,7 +66,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
*/ */
ControlFlowNode getATrueSuccessor() { ControlFlowNode getATrueSuccessor() {
qlCFGTrueSuccessor(this, result) and qlCFGTrueSuccessor(this, result) and
result = getASuccessor() result = this.getASuccessor()
} }
/** /**
@@ -75,7 +75,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
*/ */
ControlFlowNode getAFalseSuccessor() { ControlFlowNode getAFalseSuccessor() {
qlCFGFalseSuccessor(this, result) and qlCFGFalseSuccessor(this, result) and
result = getASuccessor() result = this.getASuccessor()
} }
/** Gets the `BasicBlock` containing this control-flow node. */ /** Gets the `BasicBlock` containing this control-flow node. */

View File

@@ -121,7 +121,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(boolean testIsTrue | exists(boolean testIsTrue |
comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
) )
} }
@@ -135,7 +135,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
exists(boolean testIsTrue | exists(boolean testIsTrue |
comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
) )
} }
} }
@@ -147,27 +147,29 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr { private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
GuardConditionFromShortCircuitNot() { GuardConditionFromShortCircuitNot() {
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and
exists(IRGuardCondition ir | getOperand() = ir.getAST()) exists(IRGuardCondition ir | this.getOperand() = ir.getAST())
} }
override predicate controls(BasicBlock controlled, boolean testIsTrue) { override predicate controls(BasicBlock controlled, boolean testIsTrue) {
getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot()) this.getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
} }
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
getOperand().(GuardCondition).comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot()) this.getOperand()
.(GuardCondition)
.comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
} }
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot()) this.getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
} }
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot()) this.getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
} }
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot()) this.getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
} }
} }
@@ -303,9 +305,9 @@ class IRGuardCondition extends Instruction {
cached cached
predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) { predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
pred.getASuccessor() = succ and pred.getASuccessor() = succ and
controls(pred, testIsTrue) this.controls(pred, testIsTrue)
or or
succ = getBranchSuccessor(testIsTrue) and succ = this.getBranchSuccessor(testIsTrue) and
branch.getCondition() = this and branch.getCondition() = this and
branch.getBlock() = pred branch.getBlock() = pred
} }

View File

@@ -73,19 +73,19 @@ abstract deprecated class LocalScopeVariableReachability extends string {
*/ */
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
isSource(source, v) and this.isSource(source, v) and
bb.getNode(i) = source and bb.getNode(i) = source and
not bb.isUnreachable() not bb.isUnreachable()
| |
exists(int j | exists(int j |
j > i and j > i and
sink = bb.getNode(j) and sink = bb.getNode(j) and
isSink(sink, v) and this.isSink(sink, v) and
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
) )
or or
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
bbSuccessorEntryReaches(bb, v, sink, _) this.bbSuccessorEntryReaches(bb, v, sink, _)
) )
} }
@@ -97,11 +97,11 @@ abstract deprecated class LocalScopeVariableReachability extends string {
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) succSkipsFirstLoopAlwaysTrueUponEntry)
| |
bbEntryReachesLocally(succ, v, node) and this.bbEntryReachesLocally(succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false succSkipsFirstLoopAlwaysTrueUponEntry = false
or or
not isBarrier(succ.getNode(_), v) and not this.isBarrier(succ.getNode(_), v) and
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
) )
} }
@@ -110,7 +110,7 @@ abstract deprecated class LocalScopeVariableReachability extends string {
) { ) {
exists(int n | exists(int n |
node = bb.getNode(n) and node = bb.getNode(n) and
isSink(node, v) this.isSink(node, v)
| |
not exists(this.firstBarrierIndexIn(bb, v)) not exists(this.firstBarrierIndexIn(bb, v))
or or
@@ -119,7 +119,7 @@ abstract deprecated class LocalScopeVariableReachability extends string {
} }
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) { private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
result = min(int m | isBarrier(bb.getNode(m), v)) result = min(int m | this.isBarrier(bb.getNode(m), v))
} }
} }
@@ -271,7 +271,7 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
* accounts for loops where the condition is provably true upon entry. * accounts for loops where the condition is provably true upon entry.
*/ */
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
reachesTo(source, v, sink, _) this.reachesTo(source, v, sink, _)
} }
/** /**
@@ -281,21 +281,21 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0 ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
) { ) {
exists(ControlFlowNode def | exists(ControlFlowNode def |
actualSourceReaches(source, v, def, v0) and this.actualSourceReaches(source, v, def, v0) and
LocalScopeVariableReachability.super.reaches(def, v0, sink) and LocalScopeVariableReachability.super.reaches(def, v0, sink) and
isSinkActual(sink, v0) this.isSinkActual(sink, v0)
) )
} }
private predicate actualSourceReaches( private predicate actualSourceReaches(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0 ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) { ) {
isSourceActual(source, v) and def = source and v0 = v this.isSourceActual(source, v) and def = source and v0 = v
or or
exists(ControlFlowNode source1, SemanticStackVariable v1 | exists(ControlFlowNode source1, SemanticStackVariable v1 |
actualSourceReaches(source, v, source1, v1) this.actualSourceReaches(source, v, source1, v1)
| |
reassignment(source1, v1, def, v0) this.reassignment(source1, v1, def, v0)
) )
} }
@@ -307,14 +307,14 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
} }
final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
isSourceActual(node, v) this.isSourceActual(node, v)
or or
// Reassignment generates a new (non-actual) source // Reassignment generates a new (non-actual) source
reassignment(_, _, node, v) this.reassignment(_, _, node, v)
} }
final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
isSinkActual(node, v) this.isSinkActual(node, v)
or or
// Reassignment generates a new (non-actual) sink // Reassignment generates a new (non-actual) sink
exprDefinition(_, node, v.getAnAccess()) exprDefinition(_, node, v.getAnAccess())
@@ -347,21 +347,21 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string {
/** See `LocalScopeVariableReachability.reaches`. */ /** See `LocalScopeVariableReachability.reaches`. */
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
isSource(source, v) and this.isSource(source, v) and
bb.getNode(i) = source and bb.getNode(i) = source and
not bb.isUnreachable() not bb.isUnreachable()
| |
exists(int j | exists(int j |
j > i and j > i and
sink = bb.getNode(j) and sink = bb.getNode(j) and
isSink(sink, v) and this.isSink(sink, v) and
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
k in [i .. j - 1] k in [i .. j - 1]
) )
) )
or or
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
bbSuccessorEntryReaches(source, bb, v, sink, _) this.bbSuccessorEntryReaches(source, bb, v, sink, _)
) )
} }
@@ -372,22 +372,22 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and succSkipsFirstLoopAlwaysTrueUponEntry) and
not isBarrier(source, bb.getEnd(), succ.getStart(), v) not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
| |
bbEntryReachesLocally(source, succ, v, node) and this.bbEntryReachesLocally(source, succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false succSkipsFirstLoopAlwaysTrueUponEntry = false
or or
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
) )
} }
private predicate bbEntryReachesLocally( private predicate bbEntryReachesLocally(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) { ) {
isSource(source, v) and this.isSource(source, v) and
exists(int n | node = bb.getNode(n) and isSink(node, v) | exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
) )
} }
} }

View File

@@ -59,7 +59,7 @@ class SsaDefinition extends ControlFlowNodeBase {
ControlFlowNode getDefinition() { result = this } ControlFlowNode getDefinition() { result = this }
/** Gets the `BasicBlock` containing this definition. */ /** Gets the `BasicBlock` containing this definition. */
BasicBlock getBasicBlock() { result.contains(getDefinition()) } BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
/** Holds if this definition is a phi node for variable `v`. */ /** Holds if this definition is a phi node for variable `v`. */
predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this.(BasicBlock))) } predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this.(BasicBlock))) }

View File

@@ -72,19 +72,19 @@ abstract class StackVariableReachability extends string {
*/ */
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
isSource(source, v) and this.isSource(source, v) and
bb.getNode(i) = source and bb.getNode(i) = source and
not bb.isUnreachable() not bb.isUnreachable()
| |
exists(int j | exists(int j |
j > i and j > i and
sink = bb.getNode(j) and sink = bb.getNode(j) and
isSink(sink, v) and this.isSink(sink, v) and
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
) )
or or
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
bbSuccessorEntryReaches(bb, v, sink, _) this.bbSuccessorEntryReaches(bb, v, sink, _)
) )
} }
@@ -96,11 +96,11 @@ abstract class StackVariableReachability extends string {
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) succSkipsFirstLoopAlwaysTrueUponEntry)
| |
bbEntryReachesLocally(succ, v, node) and this.bbEntryReachesLocally(succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false succSkipsFirstLoopAlwaysTrueUponEntry = false
or or
not isBarrier(succ.getNode(_), v) and not this.isBarrier(succ.getNode(_), v) and
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
) )
} }
@@ -109,7 +109,7 @@ abstract class StackVariableReachability extends string {
) { ) {
exists(int n | exists(int n |
node = bb.getNode(n) and node = bb.getNode(n) and
isSink(node, v) this.isSink(node, v)
| |
not exists(this.firstBarrierIndexIn(bb, v)) not exists(this.firstBarrierIndexIn(bb, v))
or or
@@ -118,7 +118,7 @@ abstract class StackVariableReachability extends string {
} }
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) { private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
result = min(int m | isBarrier(bb.getNode(m), v)) result = min(int m | this.isBarrier(bb.getNode(m), v))
} }
} }
@@ -268,7 +268,7 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
* accounts for loops where the condition is provably true upon entry. * accounts for loops where the condition is provably true upon entry.
*/ */
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
reachesTo(source, v, sink, _) this.reachesTo(source, v, sink, _)
} }
/** /**
@@ -278,21 +278,21 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0 ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
) { ) {
exists(ControlFlowNode def | exists(ControlFlowNode def |
actualSourceReaches(source, v, def, v0) and this.actualSourceReaches(source, v, def, v0) and
StackVariableReachability.super.reaches(def, v0, sink) and StackVariableReachability.super.reaches(def, v0, sink) and
isSinkActual(sink, v0) this.isSinkActual(sink, v0)
) )
} }
private predicate actualSourceReaches( private predicate actualSourceReaches(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0 ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) { ) {
isSourceActual(source, v) and def = source and v0 = v this.isSourceActual(source, v) and def = source and v0 = v
or or
exists(ControlFlowNode source1, SemanticStackVariable v1 | exists(ControlFlowNode source1, SemanticStackVariable v1 |
actualSourceReaches(source, v, source1, v1) this.actualSourceReaches(source, v, source1, v1)
| |
reassignment(source1, v1, def, v0) this.reassignment(source1, v1, def, v0)
) )
} }
@@ -304,14 +304,14 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
} }
final override predicate isSource(ControlFlowNode node, StackVariable v) { final override predicate isSource(ControlFlowNode node, StackVariable v) {
isSourceActual(node, v) this.isSourceActual(node, v)
or or
// Reassignment generates a new (non-actual) source // Reassignment generates a new (non-actual) source
reassignment(_, _, node, v) this.reassignment(_, _, node, v)
} }
final override predicate isSink(ControlFlowNode node, StackVariable v) { final override predicate isSink(ControlFlowNode node, StackVariable v) {
isSinkActual(node, v) this.isSinkActual(node, v)
or or
// Reassignment generates a new (non-actual) sink // Reassignment generates a new (non-actual) sink
exprDefinition(_, node, v.getAnAccess()) exprDefinition(_, node, v.getAnAccess())
@@ -342,21 +342,21 @@ abstract class StackVariableReachabilityExt extends string {
/** See `StackVariableReachability.reaches`. */ /** See `StackVariableReachability.reaches`. */
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
isSource(source, v) and this.isSource(source, v) and
bb.getNode(i) = source and bb.getNode(i) = source and
not bb.isUnreachable() not bb.isUnreachable()
| |
exists(int j | exists(int j |
j > i and j > i and
sink = bb.getNode(j) and sink = bb.getNode(j) and
isSink(sink, v) and this.isSink(sink, v) and
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
k in [i .. j - 1] k in [i .. j - 1]
) )
) )
or or
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
bbSuccessorEntryReaches(source, bb, v, sink, _) this.bbSuccessorEntryReaches(source, bb, v, sink, _)
) )
} }
@@ -367,22 +367,22 @@ abstract class StackVariableReachabilityExt extends string {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and succSkipsFirstLoopAlwaysTrueUponEntry) and
not isBarrier(source, bb.getEnd(), succ.getStart(), v) not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
| |
bbEntryReachesLocally(source, succ, v, node) and this.bbEntryReachesLocally(source, succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false succSkipsFirstLoopAlwaysTrueUponEntry = false
or or
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry) this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
) )
} }
private predicate bbEntryReachesLocally( private predicate bbEntryReachesLocally(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) { ) {
isSource(source, v) and this.isSource(source, v) and
exists(int n | node = bb.getNode(n) and isSink(node, v) | exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
) )
} }
} }

View File

@@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
* returns a 0-based position, while `getRankInBasicBlock` returns a 1-based * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based
* position. * position.
*/ */
deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 } deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 }
pragma[noinline] pragma[noinline]
private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) }
@@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
exists(BasicBlock bb | exists(BasicBlock bb |
exists(int outerIndex | exists(int outerIndex |
result = bb.getNode(outerIndex) and result = bb.getNode(outerIndex) and
index = outerToInnerIndex(bb, outerIndex) index = this.outerToInnerIndex(bb, outerIndex)
) )
) )
} }

View File

@@ -344,14 +344,13 @@ private int convertIntToType(int val, IntegralType t) {
then if val = 0 then result = 0 else result = 1 then if val = 0 then result = 0 else result = 1
else else
if t.isUnsigned() if t.isUnsigned()
then if val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 then result = val else none() then val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 and result = val
else else
if val >= 0 and val.bitShiftRight(t.getSize() * 8 - 1) = 0 if val >= 0 and val.bitShiftRight(t.getSize() * 8 - 1) = 0
then result = val then result = val
else else (
if (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 and result = val
then result = val )
else none()
} }
/** /**
@@ -386,7 +385,7 @@ library class ExprEvaluator extends int {
abstract predicate interesting(Expr e); abstract predicate interesting(Expr e);
/** Gets the value of (interesting) expression `e`, if any. */ /** Gets the value of (interesting) expression `e`, if any. */
int getValue(Expr e) { result = getValueInternal(e, e) } int getValue(Expr e) { result = this.getValueInternal(e, e) }
/** /**
* When evaluating a syntactic subexpression of `e`, we may * When evaluating a syntactic subexpression of `e`, we may
@@ -426,9 +425,9 @@ library class ExprEvaluator extends int {
* calculates the values bottom-up. * calculates the values bottom-up.
*/ */
predicate interestingInternal(Expr e, Expr req, boolean sub) { predicate interestingInternal(Expr e, Expr req, boolean sub) {
interesting(e) and req = e and sub = true this.interesting(e) and req = e and sub = true
or or
exists(Expr mid | interestingInternal(e, mid, sub) | exists(Expr mid | this.interestingInternal(e, mid, sub) |
req = mid.(NotExpr).getOperand() or req = mid.(NotExpr).getOperand() or
req = mid.(BinaryLogicalOperation).getAnOperand() or req = mid.(BinaryLogicalOperation).getAnOperand() or
req = mid.(RelationalOperation).getAnOperand() or req = mid.(RelationalOperation).getAnOperand() or
@@ -443,36 +442,36 @@ library class ExprEvaluator extends int {
) )
or or
exists(VariableAccess va, Variable v, boolean sub1 | exists(VariableAccess va, Variable v, boolean sub1 |
interestingVariableAccess(e, va, v, sub1) and this.interestingVariableAccess(e, va, v, sub1) and
req = v.getAnAssignedValue() and req = v.getAnAssignedValue() and
(sub1 = true implies not ignoreVariableAssignment(e, v, req)) and (sub1 = true implies not this.ignoreVariableAssignment(e, v, req)) and
sub = false sub = false
) )
or or
exists(Function f | exists(Function f |
interestingFunction(e, f) and this.interestingFunction(e, f) and
returnStmt(f, req) and returnStmt(f, req) and
sub = false sub = false
) )
} }
private predicate interestingVariableAccess(Expr e, VariableAccess va, Variable v, boolean sub) { private predicate interestingVariableAccess(Expr e, VariableAccess va, Variable v, boolean sub) {
interestingInternal(e, va, sub) and this.interestingInternal(e, va, sub) and
v = getVariableTarget(va) and v = getVariableTarget(va) and
( (
v.hasInitializer() v.hasInitializer()
or or
sub = true and allowVariableWithoutInitializer(e, v) sub = true and this.allowVariableWithoutInitializer(e, v)
) and ) and
tractableVariable(v) and tractableVariable(v) and
forall(StmtParent def | nonAnalyzableVariableDefinition(v, def) | forall(StmtParent def | nonAnalyzableVariableDefinition(v, def) |
sub = true and sub = true and
ignoreNonAnalyzableVariableDefinition(e, v, def) this.ignoreNonAnalyzableVariableDefinition(e, v, def)
) )
} }
private predicate interestingFunction(Expr e, Function f) { private predicate interestingFunction(Expr e, Function f) {
exists(FunctionCall fc | interestingInternal(e, fc, _) | exists(FunctionCall fc | this.interestingInternal(e, fc, _) |
f = fc.getTarget() and f = fc.getTarget() and
not obviouslyNonConstant(f) and not obviouslyNonConstant(f) and
not f.getUnspecifiedType() instanceof VoidType not f.getUnspecifiedType() instanceof VoidType
@@ -482,10 +481,10 @@ library class ExprEvaluator extends int {
/** Gets the value of subexpressions `req` for expression `e`, if any. */ /** Gets the value of subexpressions `req` for expression `e`, if any. */
private int getValueInternal(Expr e, Expr req) { private int getValueInternal(Expr e, Expr req) {
( (
interestingInternal(e, req, true) and this.interestingInternal(e, req, true) and
( (
result = req.(CompileTimeConstantInt).getIntValue() or result = req.(CompileTimeConstantInt).getIntValue() or
result = getCompoundValue(e, req.(CompileTimeVariableExpr)) result = this.getCompoundValue(e, req.(CompileTimeVariableExpr))
) and ) and
( (
req.getUnderlyingType().(IntegralType).isSigned() or req.getUnderlyingType().(IntegralType).isSigned() or
@@ -496,109 +495,126 @@ library class ExprEvaluator extends int {
/** Gets the value of compound subexpressions `val` for expression `e`, if any. */ /** Gets the value of compound subexpressions `val` for expression `e`, if any. */
private int getCompoundValue(Expr e, CompileTimeVariableExpr val) { private int getCompoundValue(Expr e, CompileTimeVariableExpr val) {
interestingInternal(e, val, true) and this.interestingInternal(e, val, true) and
( (
exists(NotExpr req | req = val | exists(NotExpr req | req = val |
result = 1 and getValueInternal(e, req.getOperand()) = 0 result = 1 and this.getValueInternal(e, req.getOperand()) = 0
or or
result = 0 and getValueInternal(e, req.getOperand()) != 0 result = 0 and this.getValueInternal(e, req.getOperand()) != 0
) )
or or
exists(LogicalAndExpr req | req = val | exists(LogicalAndExpr req | req = val |
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) != 0 and this.getValueInternal(e, req.getLeftOperand()) != 0 and
getValueInternal(e, req.getRightOperand()) != 0 this.getValueInternal(e, req.getRightOperand()) != 0
or or
result = 0 and getValueInternal(e, req.getAnOperand()) = 0 result = 0 and this.getValueInternal(e, req.getAnOperand()) = 0
) )
or or
exists(LogicalOrExpr req | req = val | exists(LogicalOrExpr req | req = val |
result = 1 and getValueInternal(e, req.getAnOperand()) != 0 result = 1 and this.getValueInternal(e, req.getAnOperand()) != 0
or or
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) = 0 and this.getValueInternal(e, req.getLeftOperand()) = 0 and
getValueInternal(e, req.getRightOperand()) = 0 this.getValueInternal(e, req.getRightOperand()) = 0
) )
or or
exists(LTExpr req | req = val | exists(LTExpr req | req = val |
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) <
this.getValueInternal(e, req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) >=
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(GTExpr req | req = val | exists(GTExpr req | req = val |
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) >
this.getValueInternal(e, req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) <=
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(LEExpr req | req = val | exists(LEExpr req | req = val |
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) <=
this.getValueInternal(e, req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) >
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(GEExpr req | req = val | exists(GEExpr req | req = val |
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) >=
this.getValueInternal(e, req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) <
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(EQExpr req | req = val | exists(EQExpr req | req = val |
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) =
this.getValueInternal(e, req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) !=
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(NEExpr req | req = val | exists(NEExpr req | req = val |
result = 0 and result = 0 and
getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) =
this.getValueInternal(e, req.getRightOperand())
or or
result = 1 and result = 1 and
getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) !=
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(AddExpr req | req = val | exists(AddExpr req | req = val |
result = result =
getValueInternal(e, req.getLeftOperand()) + getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) +
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(SubExpr req | req = val | exists(SubExpr req | req = val |
result = result =
getValueInternal(e, req.getLeftOperand()) - getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) -
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(MulExpr req | req = val | exists(MulExpr req | req = val |
result = result =
getValueInternal(e, req.getLeftOperand()) * getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) *
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(RemExpr req | req = val | exists(RemExpr req | req = val |
result = result =
getValueInternal(e, req.getLeftOperand()) % getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) %
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(DivExpr req | req = val | exists(DivExpr req | req = val |
result = result =
getValueInternal(e, req.getLeftOperand()) / getValueInternal(e, req.getRightOperand()) this.getValueInternal(e, req.getLeftOperand()) /
this.getValueInternal(e, req.getRightOperand())
) )
or or
exists(AssignExpr req | req = val | result = getValueInternal(e, req.getRValue())) exists(AssignExpr req | req = val | result = this.getValueInternal(e, req.getRValue()))
or or
result = getVariableValue(e, val.(VariableAccess)) result = this.getVariableValue(e, val.(VariableAccess))
or or
exists(FunctionCall call | call = val and not callWithMultipleTargets(call) | exists(FunctionCall call | call = val and not callWithMultipleTargets(call) |
result = getFunctionValue(call.getTarget()) result = this.getFunctionValue(call.getTarget())
) )
) )
} }
@@ -606,7 +622,7 @@ library class ExprEvaluator extends int {
language[monotonicAggregates] language[monotonicAggregates]
private int getVariableValue(Expr e, VariableAccess va) { private int getVariableValue(Expr e, VariableAccess va) {
exists(Variable v | exists(Variable v |
interestingVariableAccess(e, va, v, true) and this.interestingVariableAccess(e, va, v, true) and
// All assignments must have the same int value // All assignments must have the same int value
result = result =
unique(Expr value | unique(Expr value |
@@ -620,14 +636,16 @@ library class ExprEvaluator extends int {
/** Holds if the function `f` is considered by the analysis and may return `ret`. */ /** Holds if the function `f` is considered by the analysis and may return `ret`. */
pragma[noinline] pragma[noinline]
private predicate interestingReturnValue(Function f, Expr ret) { private predicate interestingReturnValue(Function f, Expr ret) {
interestingFunction(_, f) and this.interestingFunction(_, f) and
returnStmt(f, ret) returnStmt(f, ret)
} }
private int getFunctionValue(Function f) { private int getFunctionValue(Function f) {
// All returns must have the same int value // All returns must have the same int value
// And it must have at least one return // And it must have at least one return
forex(Expr ret | interestingReturnValue(f, ret) | result = getValueInternalNonSubExpr(ret)) forex(Expr ret | this.interestingReturnValue(f, ret) |
result = this.getValueInternalNonSubExpr(ret)
)
} }
/** /**
@@ -642,10 +660,10 @@ library class ExprEvaluator extends int {
* omitted). * omitted).
*/ */
private int getValueInternalNonSubExpr(Expr req) { private int getValueInternalNonSubExpr(Expr req) {
interestingInternal(_, req, false) and this.interestingInternal(_, req, false) and
( (
result = req.(CompileTimeConstantInt).getIntValue() or result = req.(CompileTimeConstantInt).getIntValue() or
result = getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr)) result = this.getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr))
) and ) and
( (
req.getUnderlyingType().(IntegralType).isSigned() or req.getUnderlyingType().(IntegralType).isSigned() or
@@ -656,131 +674,131 @@ library class ExprEvaluator extends int {
private int getCompoundValueNonSubExpr(CompileTimeVariableExpr val) { private int getCompoundValueNonSubExpr(CompileTimeVariableExpr val) {
( (
exists(NotExpr req | req = val | exists(NotExpr req | req = val |
result = 1 and getValueInternalNonSubExpr(req.getOperand()) = 0 result = 1 and this.getValueInternalNonSubExpr(req.getOperand()) = 0
or or
result = 0 and getValueInternalNonSubExpr(req.getOperand()) != 0 result = 0 and this.getValueInternalNonSubExpr(req.getOperand()) != 0
) )
or or
exists(LogicalAndExpr req | req = val | exists(LogicalAndExpr req | req = val |
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and this.getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and
getValueInternalNonSubExpr(req.getRightOperand()) != 0 this.getValueInternalNonSubExpr(req.getRightOperand()) != 0
or or
result = 0 and getValueInternalNonSubExpr(req.getAnOperand()) = 0 result = 0 and this.getValueInternalNonSubExpr(req.getAnOperand()) = 0
) )
or or
exists(LogicalOrExpr req | req = val | exists(LogicalOrExpr req | req = val |
result = 1 and getValueInternalNonSubExpr(req.getAnOperand()) != 0 result = 1 and this.getValueInternalNonSubExpr(req.getAnOperand()) != 0
or or
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and this.getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and
getValueInternalNonSubExpr(req.getRightOperand()) = 0 this.getValueInternalNonSubExpr(req.getRightOperand()) = 0
) )
or or
exists(LTExpr req | req = val | exists(LTExpr req | req = val |
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) < this.getValueInternalNonSubExpr(req.getLeftOperand()) <
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) >= this.getValueInternalNonSubExpr(req.getLeftOperand()) >=
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(GTExpr req | req = val | exists(GTExpr req | req = val |
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) > this.getValueInternalNonSubExpr(req.getLeftOperand()) >
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) <= this.getValueInternalNonSubExpr(req.getLeftOperand()) <=
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(LEExpr req | req = val | exists(LEExpr req | req = val |
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) <= this.getValueInternalNonSubExpr(req.getLeftOperand()) <=
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) > this.getValueInternalNonSubExpr(req.getLeftOperand()) >
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(GEExpr req | req = val | exists(GEExpr req | req = val |
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) >= this.getValueInternalNonSubExpr(req.getLeftOperand()) >=
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) < this.getValueInternalNonSubExpr(req.getLeftOperand()) <
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(EQExpr req | req = val | exists(EQExpr req | req = val |
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) = this.getValueInternalNonSubExpr(req.getLeftOperand()) =
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
or or
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) != this.getValueInternalNonSubExpr(req.getLeftOperand()) !=
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(NEExpr req | req = val | exists(NEExpr req | req = val |
result = 0 and result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) = this.getValueInternalNonSubExpr(req.getLeftOperand()) =
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
or or
result = 1 and result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) != this.getValueInternalNonSubExpr(req.getLeftOperand()) !=
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(AddExpr req | req = val | exists(AddExpr req | req = val |
result = result =
getValueInternalNonSubExpr(req.getLeftOperand()) + this.getValueInternalNonSubExpr(req.getLeftOperand()) +
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(SubExpr req | req = val | exists(SubExpr req | req = val |
result = result =
getValueInternalNonSubExpr(req.getLeftOperand()) - this.getValueInternalNonSubExpr(req.getLeftOperand()) -
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(MulExpr req | req = val | exists(MulExpr req | req = val |
result = result =
getValueInternalNonSubExpr(req.getLeftOperand()) * this.getValueInternalNonSubExpr(req.getLeftOperand()) *
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(RemExpr req | req = val | exists(RemExpr req | req = val |
result = result =
getValueInternalNonSubExpr(req.getLeftOperand()) % this.getValueInternalNonSubExpr(req.getLeftOperand()) %
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(DivExpr req | req = val | exists(DivExpr req | req = val |
result = result =
getValueInternalNonSubExpr(req.getLeftOperand()) / this.getValueInternalNonSubExpr(req.getLeftOperand()) /
getValueInternalNonSubExpr(req.getRightOperand()) this.getValueInternalNonSubExpr(req.getRightOperand())
) )
or or
exists(AssignExpr req | req = val | result = getValueInternalNonSubExpr(req.getRValue())) exists(AssignExpr req | req = val | result = this.getValueInternalNonSubExpr(req.getRValue()))
or or
result = getVariableValueNonSubExpr(val.(VariableAccess)) result = this.getVariableValueNonSubExpr(val.(VariableAccess))
or or
exists(FunctionCall call | call = val and not callWithMultipleTargets(call) | exists(FunctionCall call | call = val and not callWithMultipleTargets(call) |
result = getFunctionValue(call.getTarget()) result = this.getFunctionValue(call.getTarget())
) )
) )
} }
private int getVariableValueNonSubExpr(VariableAccess va) { private int getVariableValueNonSubExpr(VariableAccess va) {
// All assignments must have the same int value // All assignments must have the same int value
result = getMinVariableValueNonSubExpr(va) and result = this.getMinVariableValueNonSubExpr(va) and
result = getMaxVariableValueNonSubExpr(va) result = this.getMaxVariableValueNonSubExpr(va)
} }
/** /**
@@ -791,8 +809,9 @@ library class ExprEvaluator extends int {
pragma[noopt] pragma[noopt]
private int getMinVariableValueNonSubExpr(VariableAccess va) { private int getMinVariableValueNonSubExpr(VariableAccess va) {
exists(Variable v | exists(Variable v |
interestingVariableAccess(_, va, v, false) and this.interestingVariableAccess(_, va, v, false) and
result = min(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value)) result =
min(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value))
) )
} }
@@ -804,8 +823,9 @@ library class ExprEvaluator extends int {
pragma[noopt] pragma[noopt]
private int getMaxVariableValueNonSubExpr(VariableAccess va) { private int getMaxVariableValueNonSubExpr(VariableAccess va) {
exists(Variable v | exists(Variable v |
interestingVariableAccess(_, va, v, false) and this.interestingVariableAccess(_, va, v, false) and
result = max(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value)) result =
max(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value))
) )
} }
} }
@@ -968,9 +988,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
abstract predicate isLoopBody(Expr e, StmtParent s); abstract predicate isLoopBody(Expr e, StmtParent s);
private predicate isLoopBodyDescendant(Expr e, StmtParent s) { private predicate isLoopBodyDescendant(Expr e, StmtParent s) {
isLoopBody(e, s) this.isLoopBody(e, s)
or or
exists(StmtParent mid | isLoopBodyDescendant(e, mid) | exists(StmtParent mid | this.isLoopBodyDescendant(e, mid) |
s = mid.(Stmt).getAChild() or s = mid.(Stmt).getAChild() or
s = mid.(Expr).getAChild() s = mid.(Expr).getAChild()
) )
@@ -978,13 +998,13 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
// Same as `interestingInternal(e, sub, true)` but avoids negative recursion // Same as `interestingInternal(e, sub, true)` but avoids negative recursion
private predicate interestingSubExpr(Expr e, Expr sub) { private predicate interestingSubExpr(Expr e, Expr sub) {
interesting(e) and e = sub this.interesting(e) and e = sub
or or
exists(Expr mid | interestingSubExpr(e, mid) and sub = mid.getAChild()) exists(Expr mid | this.interestingSubExpr(e, mid) and sub = mid.getAChild())
} }
private predicate maybeInterestingVariable(Expr e, Variable v) { private predicate maybeInterestingVariable(Expr e, Variable v) {
exists(VariableAccess va | interestingSubExpr(e, va) | va.getTarget() = v) exists(VariableAccess va | this.interestingSubExpr(e, va) | va.getTarget() = v)
} }
/** /**
@@ -996,9 +1016,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* definition of `v`. * definition of `v`.
*/ */
private predicate reachesLoopEntryFromLoopBody(Expr e, Variable v, StmtParent valueOrDef) { private predicate reachesLoopEntryFromLoopBody(Expr e, Variable v, StmtParent valueOrDef) {
maybeInterestingVariable(e, v) and this.maybeInterestingVariable(e, v) and
(valueOrDef = v.getAnAssignedValue() or nonAnalyzableVariableDefinition(v, valueOrDef)) and (valueOrDef = v.getAnAssignedValue() or nonAnalyzableVariableDefinition(v, valueOrDef)) and
isLoopBodyDescendant(e, valueOrDef) and this.isLoopBodyDescendant(e, valueOrDef) and
/* /*
* Use primitive basic blocks in reachability analysis for better performance. * Use primitive basic blocks in reachability analysis for better performance.
* This is similar to the pattern used in e.g. `DefinitionsAndUses` and * This is similar to the pattern used in e.g. `DefinitionsAndUses` and
@@ -1008,16 +1028,16 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef | exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef |
// Reaches in same basic block // Reaches in same basic block
exists(int pos2 | exists(int pos2 |
loopEntryAt(bb1, pos2, e) and this.loopEntryAt(bb1, pos2, e) and
pos2 > pos1 and pos2 > pos1 and
not exists(int k | assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1]) not exists(int k | this.assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1])
) )
or or
// Reaches in a successor block // Reaches in a successor block
exists(PrimitiveBasicBlock bb2 | exists(PrimitiveBasicBlock bb2 |
bb2 = bb1.getASuccessor() and bb2 = bb1.getASuccessor() and
not exists(int pos3 | assignmentAt(bb1, pos3, v) and pos3 > pos1) and not exists(int pos3 | this.assignmentAt(bb1, pos3, v) and pos3 > pos1) and
bbReachesLoopEntry(bb2, e, v) this.bbReachesLoopEntry(bb2, e, v)
) )
) )
} }
@@ -1025,12 +1045,12 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
private predicate loopEntryAt(PrimitiveBasicBlock bb, int pos, Expr e) { private predicate loopEntryAt(PrimitiveBasicBlock bb, int pos, Expr e) {
exists(Node cfn | exists(Node cfn |
bb.getNode(pos) = cfn and bb.getNode(pos) = cfn and
isLoopEntry(e, cfn) this.isLoopEntry(e, cfn)
) )
} }
private predicate assignmentAt(PrimitiveBasicBlock bb, int pos, Variable v) { private predicate assignmentAt(PrimitiveBasicBlock bb, int pos, Variable v) {
maybeInterestingVariable(_, v) and this.maybeInterestingVariable(_, v) and
bb.getNode(pos) = v.getAnAssignedValue() bb.getNode(pos) = v.getAnAssignedValue()
} }
@@ -1039,19 +1059,19 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* the loop belonging to `e` without crossing an assignment to `v`. * the loop belonging to `e` without crossing an assignment to `v`.
*/ */
private predicate bbReachesLoopEntry(PrimitiveBasicBlock bb, Expr e, Variable v) { private predicate bbReachesLoopEntry(PrimitiveBasicBlock bb, Expr e, Variable v) {
bbReachesLoopEntryLocally(bb, e, v) this.bbReachesLoopEntryLocally(bb, e, v)
or or
exists(PrimitiveBasicBlock succ | succ = bb.getASuccessor() | exists(PrimitiveBasicBlock succ | succ = bb.getASuccessor() |
bbReachesLoopEntry(succ, e, v) and this.bbReachesLoopEntry(succ, e, v) and
not assignmentAt(bb, _, v) not this.assignmentAt(bb, _, v)
) )
} }
private predicate bbReachesLoopEntryLocally(PrimitiveBasicBlock bb, Expr e, Variable v) { private predicate bbReachesLoopEntryLocally(PrimitiveBasicBlock bb, Expr e, Variable v) {
exists(int pos | exists(int pos |
loopEntryAt(bb, pos, e) and this.loopEntryAt(bb, pos, e) and
maybeInterestingVariable(e, v) and this.maybeInterestingVariable(e, v) and
not exists(int pos1 | assignmentAt(bb, pos1, v) | pos1 < pos) not exists(int pos1 | this.assignmentAt(bb, pos1, v) | pos1 < pos)
) )
} }
@@ -1085,10 +1105,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* ``` * ```
*/ */
override predicate ignoreNonAnalyzableVariableDefinition(Expr e, Variable v, StmtParent def) { override predicate ignoreNonAnalyzableVariableDefinition(Expr e, Variable v, StmtParent def) {
maybeInterestingVariable(e, v) and this.maybeInterestingVariable(e, v) and
nonAnalyzableVariableDefinition(v, def) and nonAnalyzableVariableDefinition(v, def) and
isLoopBodyDescendant(e, def) and this.isLoopBodyDescendant(e, def) and
not reachesLoopEntryFromLoopBody(e, v, def) not this.reachesLoopEntryFromLoopBody(e, v, def)
} }
/** /**
@@ -1121,10 +1141,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* ``` * ```
*/ */
override predicate ignoreVariableAssignment(Expr e, Variable v, Expr value) { override predicate ignoreVariableAssignment(Expr e, Variable v, Expr value) {
maybeInterestingVariable(e, v) and this.maybeInterestingVariable(e, v) and
value = v.getAnAssignedValue() and value = v.getAnAssignedValue() and
isLoopBodyDescendant(e, value) and this.isLoopBodyDescendant(e, value) and
not reachesLoopEntryFromLoopBody(e, v, value) not this.reachesLoopEntryFromLoopBody(e, v, value)
} }
} }

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -801,6 +801,9 @@ private module Cached {
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
} }
cached
predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) }
cached cached
newtype TCallContext = newtype TCallContext =
TAnyCallContext() or TAnyCallContext() or
@@ -937,7 +940,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
} }
override predicate relevantFor(DataFlowCallable callable) { override predicate relevantFor(DataFlowCallable callable) {
recordDataFlowCallSite(getCall(), callable) recordDataFlowCallSite(this.getCall(), callable)
} }
override predicate matchesCall(DataFlowCall call) { call = this.getCall() } override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
@@ -1236,6 +1239,13 @@ class TypedContent extends MkTypedContent {
/** Gets a textual representation of this content. */ /** Gets a textual representation of this content. */
string toString() { result = c.toString() } string toString() { result = c.toString() }
/**
* Holds if access paths with this `TypedContent` at their head always should
* be tracked at high precision. This disables adaptive access path precision
* for such access paths.
*/
predicate forceHighPrecision() { forceHighPrecision(c) }
} }
/** /**
@@ -1250,7 +1260,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) } TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
} }
class AccessPathFrontNil extends AccessPathFront, TFrontNil { class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -175,6 +175,7 @@ module Consistency {
query predicate postWithInFlow(Node n, string msg) { query predicate postWithInFlow(Node n, string msg) {
isPostUpdateNode(n) and isPostUpdateNode(n) and
not clearsContent(n, _) and
simpleLocalFlowStep(_, n) and simpleLocalFlowStep(_, n) and
msg = "PostUpdateNode should not be the target of local flow." msg = "PostUpdateNode should not be the target of local flow."
} }

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -219,15 +219,13 @@ class DataFlowExpr = Expr;
class DataFlowType = Type; class DataFlowType = Type;
/** A function call relevant for data flow. */ /** A function call relevant for data flow. */
class DataFlowCall extends Expr { class DataFlowCall extends Expr instanceof Call {
DataFlowCall() { this instanceof Call }
/** /**
* Gets the nth argument for this call. * Gets the nth argument for this call.
* *
* The range of `n` is from `0` to `getNumberOfArguments() - 1`. * The range of `n` is from `0` to `getNumberOfArguments() - 1`.
*/ */
Expr getArgument(int n) { result = this.(Call).getArgument(n) } Expr getArgument(int n) { result = super.getArgument(n) }
/** Gets the data flow node corresponding to this call. */ /** Gets the data flow node corresponding to this call. */
ExprNode getNode() { result.getExpr() = this } ExprNode getNode() { result.getExpr() = this }
@@ -240,6 +238,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl
int accessPathLimit() { result = 5 } int accessPathLimit() { result = 5 }
/**
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) { none() }
/** The unit type. */ /** The unit type. */
private newtype TUnit = TMkUnit() private newtype TUnit = TMkUnit()
@@ -283,3 +287,12 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
/** Extra data-flow steps needed for lambda flow analysis. */ /** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.
*
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p) { none() }

View File

@@ -101,18 +101,18 @@ class Node extends TNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
} }
/** /**
* Gets an upper bound on the type of this node. * Gets an upper bound on the type of this node.
*/ */
Type getTypeBound() { result = getType() } Type getTypeBound() { result = this.getType() }
} }
/** /**
@@ -293,11 +293,11 @@ abstract class PostUpdateNode extends Node {
*/ */
abstract Node getPreUpdateNode(); abstract Node getPreUpdateNode();
override Function getFunction() { result = getPreUpdateNode().getFunction() } override Function getFunction() { result = this.getPreUpdateNode().getFunction() }
override Type getType() { result = getPreUpdateNode().getType() } override Type getType() { result = this.getPreUpdateNode().getType() }
override Location getLocation() { result = getPreUpdateNode().getLocation() } override Location getLocation() { result = this.getPreUpdateNode().getLocation() }
} }
abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
@@ -309,7 +309,7 @@ abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDef
PartialDefinition getPartialDefinition() { result = pd } PartialDefinition getPartialDefinition() { result = pd }
override string toString() { result = getPreUpdateNode().toString() + " [post update]" } override string toString() { result = this.getPreUpdateNode().toString() + " [post update]" }
} }
private class VariablePartialDefinitionNode extends PartialDefinitionNode { private class VariablePartialDefinitionNode extends PartialDefinitionNode {
@@ -380,13 +380,13 @@ private class ObjectInitializerNode extends PostUpdateNode, TExprNode {
class PreObjectInitializerNode extends Node, TPreObjectInitializerNode { class PreObjectInitializerNode extends Node, TPreObjectInitializerNode {
Expr getExpr() { this = TPreObjectInitializerNode(result) } Expr getExpr() { this = TPreObjectInitializerNode(result) }
override Function getFunction() { result = getExpr().getEnclosingFunction() } override Function getFunction() { result = this.getExpr().getEnclosingFunction() }
override Type getType() { result = getExpr().getType() } override Type getType() { result = this.getExpr().getType() }
override Location getLocation() { result = getExpr().getLocation() } override Location getLocation() { result = this.getExpr().getLocation() }
override string toString() { result = getExpr().toString() + " [pre init]" } override string toString() { result = this.getExpr().toString() + " [pre init]" }
} }
/** /**
@@ -401,7 +401,7 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn
} }
override string toString() { override string toString() {
result = getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]" result = this.getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]"
} }
} }
@@ -416,15 +416,17 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn
class PreConstructorInitThis extends Node, TPreConstructorInitThis { class PreConstructorInitThis extends Node, TPreConstructorInitThis {
ConstructorFieldInit getConstructorFieldInit() { this = TPreConstructorInitThis(result) } ConstructorFieldInit getConstructorFieldInit() { this = TPreConstructorInitThis(result) }
override Constructor getFunction() { result = getConstructorFieldInit().getEnclosingFunction() } override Constructor getFunction() {
result = this.getConstructorFieldInit().getEnclosingFunction()
override PointerType getType() {
result.getBaseType() = getConstructorFieldInit().getEnclosingFunction().getDeclaringType()
} }
override Location getLocation() { result = getConstructorFieldInit().getLocation() } override PointerType getType() {
result.getBaseType() = this.getConstructorFieldInit().getEnclosingFunction().getDeclaringType()
}
override string toString() { result = getConstructorFieldInit().toString() + " [pre-this]" } override Location getLocation() { result = this.getConstructorFieldInit().getLocation() }
override string toString() { result = this.getConstructorFieldInit().toString() + " [pre-this]" }
} }
/** /**

View File

@@ -354,7 +354,7 @@ module FlowVar_internal {
result = def.getAUse(v) result = def.getAUse(v)
or or
exists(SsaDefinition descendentDef | exists(SsaDefinition descendentDef |
getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and this.getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and
result = descendentDef.getAUse(v) result = descendentDef.getAUse(v)
) )
) )
@@ -515,7 +515,7 @@ module FlowVar_internal {
this.bbInLoopCondition(bbInside) and this.bbInLoopCondition(bbInside) and
not this.bbInLoop(bbOutside) and not this.bbInLoop(bbOutside) and
bbOutside = bbInside.getASuccessor() and bbOutside = bbInside.getASuccessor() and
not reachesWithoutAssignment(bbInside, v) not this.reachesWithoutAssignment(bbInside, v)
} }
/** /**
@@ -546,7 +546,7 @@ module FlowVar_internal {
private predicate bbInLoop(BasicBlock bb) { private predicate bbInLoop(BasicBlock bb) {
bbDominates(this.(Loop).getStmt(), bb) bbDominates(this.(Loop).getStmt(), bb)
or or
bbInLoopCondition(bb) this.bbInLoopCondition(bb)
} }
/** Holds if `sbb` is inside this loop. */ /** Holds if `sbb` is inside this loop. */
@@ -563,7 +563,7 @@ module FlowVar_internal {
bb = this.(Loop).getStmt() and bb = this.(Loop).getStmt() and
v = this.getARelevantVariable() v = this.getARelevantVariable()
or or
reachesWithoutAssignment(bb.getAPredecessor(), v) and this.reachesWithoutAssignment(bb.getAPredecessor(), v) and
this.bbInLoop(bb) this.bbInLoop(bb)
) and ) and
not assignsToVar(bb, v) not assignsToVar(bb, v)

View File

@@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
* returns a 0-based position, while `getRankInBasicBlock` returns a 1-based * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based
* position. * position.
*/ */
deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 } deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 }
pragma[noinline] pragma[noinline]
private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) }
@@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
exists(BasicBlock bb | exists(BasicBlock bb |
exists(int outerIndex | exists(int outerIndex |
result = bb.getNode(outerIndex) and result = bb.getNode(outerIndex) and
index = outerToInnerIndex(bb, outerIndex) index = this.outerToInnerIndex(bb, outerIndex)
) )
) )
} }

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or this.isSanitizer(node) or
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() } predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or this.isSanitizer(node) or
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() } predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }

View File

@@ -203,7 +203,7 @@ class PointerFieldAccess extends FieldAccess {
PointerFieldAccess() { PointerFieldAccess() {
exists(PointerType t | exists(PointerType t |
t = getQualifier().getFullyConverted().getUnspecifiedType() and t = this.getQualifier().getFullyConverted().getUnspecifiedType() and
t.getBaseType() instanceof Class t.getBaseType() instanceof Class
) )
} }
@@ -218,7 +218,9 @@ class PointerFieldAccess extends FieldAccess {
class DotFieldAccess extends FieldAccess { class DotFieldAccess extends FieldAccess {
override string getAPrimaryQlClass() { result = "DotFieldAccess" } override string getAPrimaryQlClass() { result = "DotFieldAccess" }
DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) } DotFieldAccess() {
exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType())
}
} }
/** /**

View File

@@ -148,7 +148,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post
override int getPrecedence() { result = 17 } override int getPrecedence() { result = 17 }
override string toString() { result = "... " + getOperator() } override string toString() { result = "... " + this.getOperator() }
} }
/** /**
@@ -166,7 +166,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post
override int getPrecedence() { result = 17 } override int getPrecedence() { result = 17 }
override string toString() { result = "... " + getOperator() } override string toString() { result = "... " + this.getOperator() }
} }
/** /**

View File

@@ -35,12 +35,12 @@ class BuiltInVarArgsStart extends VarArgsExpr, @vastartexpr {
/** /**
* Gets the `va_list` argument. * Gets the `va_list` argument.
*/ */
final Expr getVAList() { result = getChild(0) } final Expr getVAList() { result = this.getChild(0) }
/** /**
* Gets the argument that specifies the last named parameter before the ellipsis. * Gets the argument that specifies the last named parameter before the ellipsis.
*/ */
final VariableAccess getLastNamedParameter() { result = getChild(1) } final VariableAccess getLastNamedParameter() { result = this.getChild(1) }
} }
/** /**
@@ -60,7 +60,7 @@ class BuiltInVarArgsEnd extends VarArgsExpr, @vaendexpr {
/** /**
* Gets the `va_list` argument. * Gets the `va_list` argument.
*/ */
final Expr getVAList() { result = getChild(0) } final Expr getVAList() { result = this.getChild(0) }
} }
/** /**
@@ -78,7 +78,7 @@ class BuiltInVarArg extends VarArgsExpr, @vaargexpr {
/** /**
* Gets the `va_list` argument. * Gets the `va_list` argument.
*/ */
final Expr getVAList() { result = getChild(0) } final Expr getVAList() { result = this.getChild(0) }
} }
/** /**
@@ -98,12 +98,12 @@ class BuiltInVarArgCopy extends VarArgsExpr, @vacopyexpr {
/** /**
* Gets the destination `va_list` argument. * Gets the destination `va_list` argument.
*/ */
final Expr getDestinationVAList() { result = getChild(0) } final Expr getDestinationVAList() { result = this.getChild(0) }
/** /**
* Gets the the source `va_list` argument. * Gets the the source `va_list` argument.
*/ */
final Expr getSourceVAList() { result = getChild(1) } final Expr getSourceVAList() { result = this.getChild(1) }
} }
/** /**

View File

@@ -71,10 +71,10 @@ class Call extends Expr, NameQualifiableElement, TCall {
* at index 2, respectively. * at index 2, respectively.
*/ */
Expr getAnArgumentSubExpr(int index) { Expr getAnArgumentSubExpr(int index) {
result = getArgument(index) result = this.getArgument(index)
or or
exists(Expr mid | exists(Expr mid |
mid = getAnArgumentSubExpr(index) and mid = this.getAnArgumentSubExpr(index) and
not mid instanceof Call and not mid instanceof Call and
not mid instanceof SizeofOperator and not mid instanceof SizeofOperator and
result = mid.getAChild() result = mid.getAChild()
@@ -167,27 +167,27 @@ class FunctionCall extends Call, @funbindexpr {
override string getAPrimaryQlClass() { result = "FunctionCall" } override string getAPrimaryQlClass() { result = "FunctionCall" }
/** Gets an explicit template argument for this call. */ /** Gets an explicit template argument for this call. */
Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } Locatable getAnExplicitTemplateArgument() { result = this.getExplicitTemplateArgument(_) }
/** Gets an explicit template argument value for this call. */ /** Gets an explicit template argument value for this call. */
Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) } Locatable getAnExplicitTemplateArgumentKind() { result = this.getExplicitTemplateArgumentKind(_) }
/** Gets a template argument for this call. */ /** Gets a template argument for this call. */
Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() } Locatable getATemplateArgument() { result = this.getTarget().getATemplateArgument() }
/** Gets a template argument value for this call. */ /** Gets a template argument value for this call. */
Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() } Locatable getATemplateArgumentKind() { result = this.getTarget().getATemplateArgumentKind() }
/** Gets the nth explicit template argument for this call. */ /** Gets the nth explicit template argument for this call. */
Locatable getExplicitTemplateArgument(int n) { Locatable getExplicitTemplateArgument(int n) {
n < getNumberOfExplicitTemplateArguments() and n < this.getNumberOfExplicitTemplateArguments() and
result = getTemplateArgument(n) result = this.getTemplateArgument(n)
} }
/** Gets the nth explicit template argument value for this call. */ /** Gets the nth explicit template argument value for this call. */
Locatable getExplicitTemplateArgumentKind(int n) { Locatable getExplicitTemplateArgumentKind(int n) {
n < getNumberOfExplicitTemplateArguments() and n < this.getNumberOfExplicitTemplateArguments() and
result = getTemplateArgumentKind(n) result = this.getTemplateArgumentKind(n)
} }
/** Gets the number of explicit template arguments for this call. */ /** Gets the number of explicit template arguments for this call. */
@@ -198,19 +198,19 @@ class FunctionCall extends Call, @funbindexpr {
} }
/** Gets the number of template arguments for this call. */ /** Gets the number of template arguments for this call. */
int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } int getNumberOfTemplateArguments() { result = count(int i | exists(this.getTemplateArgument(i))) }
/** Gets the nth template argument for this call (indexed from 0). */ /** Gets the nth template argument for this call (indexed from 0). */
Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } Locatable getTemplateArgument(int n) { result = this.getTarget().getTemplateArgument(n) }
/** Gets the nth template argument value for this call (indexed from 0). */ /** Gets the nth template argument value for this call (indexed from 0). */
Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) } Locatable getTemplateArgumentKind(int n) { result = this.getTarget().getTemplateArgumentKind(n) }
/** Holds if any template arguments for this call are implicit / deduced. */ /** Holds if any template arguments for this call are implicit / deduced. */
predicate hasImplicitTemplateArguments() { predicate hasImplicitTemplateArguments() {
exists(int i | exists(int i |
exists(getTemplateArgument(i)) and exists(this.getTemplateArgument(i)) and
not exists(getExplicitTemplateArgument(i)) not exists(this.getExplicitTemplateArgument(i))
) )
} }
@@ -233,9 +233,9 @@ class FunctionCall extends Call, @funbindexpr {
* visible at the call site. * visible at the call site.
*/ */
Type getExpectedReturnType() { Type getExpectedReturnType() {
if getTargetType() instanceof RoutineType if this.getTargetType() instanceof RoutineType
then result = getTargetType().(RoutineType).getReturnType() then result = this.getTargetType().(RoutineType).getReturnType()
else result = getTarget().getType() else result = this.getTarget().getType()
} }
/** /**
@@ -247,9 +247,9 @@ class FunctionCall extends Call, @funbindexpr {
* was visible at the call site. * was visible at the call site.
*/ */
Type getExpectedParameterType(int n) { Type getExpectedParameterType(int n) {
if getTargetType() instanceof RoutineType if this.getTargetType() instanceof RoutineType
then result = getTargetType().(RoutineType).getParameterType(n) then result = this.getTargetType().(RoutineType).getParameterType(n)
else result = getTarget().getParameter(n).getType() else result = this.getTarget().getParameter(n).getType()
} }
/** /**
@@ -263,7 +263,7 @@ class FunctionCall extends Call, @funbindexpr {
/** /**
* Gets the type of this expression, that is, the return type of the function being called. * Gets the type of this expression, that is, the return type of the function being called.
*/ */
override Type getType() { result = getExpectedReturnType() } override Type getType() { result = this.getExpectedReturnType() }
/** /**
* Holds if this is a call to a virtual function. * Holds if this is a call to a virtual function.
@@ -280,7 +280,7 @@ class FunctionCall extends Call, @funbindexpr {
/** Gets a textual representation of this function call. */ /** Gets a textual representation of this function call. */
override string toString() { override string toString() {
if exists(getTarget()) if exists(this.getTarget())
then result = "call to " + this.getTarget().getName() then result = "call to " + this.getTarget().getName()
else result = "call to unknown function" else result = "call to unknown function"
} }
@@ -288,15 +288,15 @@ class FunctionCall extends Call, @funbindexpr {
override predicate mayBeImpure() { override predicate mayBeImpure() {
this.getChild(_).mayBeImpure() or this.getChild(_).mayBeImpure() or
this.getTarget().mayHaveSideEffects() or this.getTarget().mayHaveSideEffects() or
isVirtual() or this.isVirtual() or
getTarget().getAnAttribute().getName() = "weak" this.getTarget().getAnAttribute().getName() = "weak"
} }
override predicate mayBeGloballyImpure() { override predicate mayBeGloballyImpure() {
this.getChild(_).mayBeGloballyImpure() or this.getChild(_).mayBeGloballyImpure() or
this.getTarget().mayHaveSideEffects() or this.getTarget().mayHaveSideEffects() or
isVirtual() or this.isVirtual() or
getTarget().getAnAttribute().getName() = "weak" this.getTarget().getAnAttribute().getName() = "weak"
} }
} }
@@ -367,7 +367,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
* ``` * ```
*/ */
class OverloadedArrayExpr extends FunctionCall { class OverloadedArrayExpr extends FunctionCall {
OverloadedArrayExpr() { getTarget().hasName("operator[]") } OverloadedArrayExpr() { this.getTarget().hasName("operator[]") }
override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" } override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" }
@@ -585,7 +585,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
*/ */
Expr getExpr() { result = this.getChild(0) } Expr getExpr() { result = this.getChild(0) }
override string toString() { result = "constructor init of field " + getTarget().getName() } override string toString() { result = "constructor init of field " + this.getTarget().getName() }
override predicate mayBeImpure() { this.getExpr().mayBeImpure() } override predicate mayBeImpure() { this.getExpr().mayBeImpure() }

View File

@@ -188,8 +188,8 @@ private predicate isPointerToMemberOrNullPointer(Type type) {
class ArithmeticConversion extends Cast { class ArithmeticConversion extends Cast {
ArithmeticConversion() { ArithmeticConversion() {
conversionkinds(underlyingElement(this), 0) and conversionkinds(underlyingElement(this), 0) and
isArithmeticOrEnum(getUnspecifiedType()) and isArithmeticOrEnum(this.getUnspecifiedType()) and
isArithmeticOrEnum(getExpr().getUnspecifiedType()) isArithmeticOrEnum(this.getExpr().getUnspecifiedType())
} }
override string getSemanticConversionString() { result = "arithmetic conversion" } override string getSemanticConversionString() { result = "arithmetic conversion" }
@@ -204,8 +204,8 @@ class ArithmeticConversion extends Cast {
*/ */
class IntegralConversion extends ArithmeticConversion { class IntegralConversion extends ArithmeticConversion {
IntegralConversion() { IntegralConversion() {
isIntegralOrEnum(getUnspecifiedType()) and isIntegralOrEnum(this.getUnspecifiedType()) and
isIntegralOrEnum(getExpr().getUnspecifiedType()) isIntegralOrEnum(this.getExpr().getUnspecifiedType())
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -224,8 +224,8 @@ class IntegralConversion extends ArithmeticConversion {
*/ */
class FloatingPointConversion extends ArithmeticConversion { class FloatingPointConversion extends ArithmeticConversion {
FloatingPointConversion() { FloatingPointConversion() {
getUnspecifiedType() instanceof FloatingPointType and this.getUnspecifiedType() instanceof FloatingPointType and
getExpr().getUnspecifiedType() instanceof FloatingPointType this.getExpr().getUnspecifiedType() instanceof FloatingPointType
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -244,8 +244,8 @@ class FloatingPointConversion extends ArithmeticConversion {
*/ */
class FloatingPointToIntegralConversion extends ArithmeticConversion { class FloatingPointToIntegralConversion extends ArithmeticConversion {
FloatingPointToIntegralConversion() { FloatingPointToIntegralConversion() {
isIntegralOrEnum(getUnspecifiedType()) and isIntegralOrEnum(this.getUnspecifiedType()) and
getExpr().getUnspecifiedType() instanceof FloatingPointType this.getExpr().getUnspecifiedType() instanceof FloatingPointType
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -264,8 +264,8 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
*/ */
class IntegralToFloatingPointConversion extends ArithmeticConversion { class IntegralToFloatingPointConversion extends ArithmeticConversion {
IntegralToFloatingPointConversion() { IntegralToFloatingPointConversion() {
getUnspecifiedType() instanceof FloatingPointType and this.getUnspecifiedType() instanceof FloatingPointType and
isIntegralOrEnum(getExpr().getUnspecifiedType()) isIntegralOrEnum(this.getExpr().getUnspecifiedType())
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -290,8 +290,8 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
class PointerConversion extends Cast { class PointerConversion extends Cast {
PointerConversion() { PointerConversion() {
conversionkinds(underlyingElement(this), 0) and conversionkinds(underlyingElement(this), 0) and
isPointerOrNullPointer(getUnspecifiedType()) and isPointerOrNullPointer(this.getUnspecifiedType()) and
isPointerOrNullPointer(getExpr().getUnspecifiedType()) isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
} }
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" } override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" }
@@ -315,8 +315,8 @@ class PointerToMemberConversion extends Cast {
PointerToMemberConversion() { PointerToMemberConversion() {
conversionkinds(underlyingElement(this), 0) and conversionkinds(underlyingElement(this), 0) and
exists(Type fromType, Type toType | exists(Type fromType, Type toType |
fromType = getExpr().getUnspecifiedType() and fromType = this.getExpr().getUnspecifiedType() and
toType = getUnspecifiedType() and toType = this.getUnspecifiedType() and
isPointerToMemberOrNullPointer(fromType) and isPointerToMemberOrNullPointer(fromType) and
isPointerToMemberOrNullPointer(toType) and isPointerToMemberOrNullPointer(toType) and
// A conversion from nullptr to nullptr is a `PointerConversion`, not a // A conversion from nullptr to nullptr is a `PointerConversion`, not a
@@ -345,8 +345,8 @@ class PointerToMemberConversion extends Cast {
class PointerToIntegralConversion extends Cast { class PointerToIntegralConversion extends Cast {
PointerToIntegralConversion() { PointerToIntegralConversion() {
conversionkinds(underlyingElement(this), 0) and conversionkinds(underlyingElement(this), 0) and
isIntegralOrEnum(getUnspecifiedType()) and isIntegralOrEnum(this.getUnspecifiedType()) and
isPointerOrNullPointer(getExpr().getUnspecifiedType()) isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -366,8 +366,8 @@ class PointerToIntegralConversion extends Cast {
class IntegralToPointerConversion extends Cast { class IntegralToPointerConversion extends Cast {
IntegralToPointerConversion() { IntegralToPointerConversion() {
conversionkinds(underlyingElement(this), 0) and conversionkinds(underlyingElement(this), 0) and
isPointerOrNullPointer(getUnspecifiedType()) and isPointerOrNullPointer(this.getUnspecifiedType()) and
isIntegralOrEnum(getExpr().getUnspecifiedType()) isIntegralOrEnum(this.getExpr().getUnspecifiedType())
} }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {
@@ -403,7 +403,7 @@ class BoolConversion extends Cast {
class VoidConversion extends Cast { class VoidConversion extends Cast {
VoidConversion() { VoidConversion() {
conversionkinds(underlyingElement(this), 0) and conversionkinds(underlyingElement(this), 0) and
getUnspecifiedType() instanceof VoidType this.getUnspecifiedType() instanceof VoidType
} }
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" } override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" }
@@ -434,8 +434,8 @@ class InheritanceConversion extends Cast {
* conversion is to an indirect virtual base class. * conversion is to an indirect virtual base class.
*/ */
final ClassDerivation getDerivation() { final ClassDerivation getDerivation() {
result.getBaseClass() = getBaseClass() and result.getBaseClass() = this.getBaseClass() and
result.getDerivedClass() = getDerivedClass() result.getDerivedClass() = this.getDerivedClass()
} }
/** /**
@@ -490,12 +490,12 @@ class BaseClassConversion extends InheritanceConversion {
override Class getBaseClass() { result = getConversionClass(this) } override Class getBaseClass() { result = getConversionClass(this) }
override Class getDerivedClass() { result = getConversionClass(getExpr()) } override Class getDerivedClass() { result = getConversionClass(this.getExpr()) }
/** /**
* Holds if this conversion is to a virtual base class. * Holds if this conversion is to a virtual base class.
*/ */
predicate isVirtual() { getDerivation().isVirtual() or not exists(getDerivation()) } predicate isVirtual() { this.getDerivation().isVirtual() or not exists(this.getDerivation()) }
} }
/** /**
@@ -515,7 +515,7 @@ class DerivedClassConversion extends InheritanceConversion {
override string getSemanticConversionString() { result = "derived class conversion" } override string getSemanticConversionString() { result = "derived class conversion" }
override Class getBaseClass() { result = getConversionClass(getExpr()) } override Class getBaseClass() { result = getConversionClass(this.getExpr()) }
override Class getDerivedClass() { result = getConversionClass(this) } override Class getDerivedClass() { result = getConversionClass(this) }
} }
@@ -637,8 +637,8 @@ class DynamicCast extends Cast, @dynamic_cast {
*/ */
class UuidofOperator extends Expr, @uuidof { class UuidofOperator extends Expr, @uuidof {
override string toString() { override string toString() {
if exists(getTypeOperand()) if exists(this.getTypeOperand())
then result = "__uuidof(" + getTypeOperand().getName() + ")" then result = "__uuidof(" + this.getTypeOperand().getName() + ")"
else result = "__uuidof(0)" else result = "__uuidof(0)"
} }

View File

@@ -26,7 +26,7 @@ class Expr extends StmtParent, @expr {
Function getEnclosingFunction() { result = exprEnclosingElement(this) } Function getEnclosingFunction() { result = exprEnclosingElement(this) }
/** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */ /** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */
BlockStmt getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() } BlockStmt getEnclosingBlock() { result = this.getEnclosingStmt().getEnclosingBlock() }
override Stmt getEnclosingStmt() { override Stmt getEnclosingStmt() {
result = this.getParent().(Expr).getEnclosingStmt() result = this.getParent().(Expr).getEnclosingStmt()
@@ -219,13 +219,13 @@ class Expr extends StmtParent, @expr {
* Holds if this expression is a _glvalue_. A _glvalue_ is either an _lvalue_ or an * Holds if this expression is a _glvalue_. A _glvalue_ is either an _lvalue_ or an
* _xvalue_. * _xvalue_.
*/ */
predicate isGLValueCategory() { isLValueCategory() or isXValueCategory() } predicate isGLValueCategory() { this.isLValueCategory() or this.isXValueCategory() }
/** /**
* Holds if this expression is an _rvalue_. An _rvalue_ is either a _prvalue_ or an * Holds if this expression is an _rvalue_. An _rvalue_ is either a _prvalue_ or an
* _xvalue_. * _xvalue_.
*/ */
predicate isRValueCategory() { isPRValueCategory() or isXValueCategory() } predicate isRValueCategory() { this.isPRValueCategory() or this.isXValueCategory() }
/** /**
* Gets a string representation of the value category of the expression. * Gets a string representation of the value category of the expression.
@@ -240,15 +240,15 @@ class Expr extends StmtParent, @expr {
* `hasLValueToRvalueConversion()` holds. * `hasLValueToRvalueConversion()` holds.
*/ */
string getValueCategoryString() { string getValueCategoryString() {
isLValueCategory() and this.isLValueCategory() and
result = "lvalue" result = "lvalue"
or or
isXValueCategory() and this.isXValueCategory() and
result = "xvalue" result = "xvalue"
or or
( (
isPRValueCategory() and this.isPRValueCategory() and
if hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue" if this.hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue"
) )
} }
@@ -263,7 +263,7 @@ class Expr extends StmtParent, @expr {
* such as an expression inside a sizeof. * such as an expression inside a sizeof.
*/ */
predicate isUnevaluated() { predicate isUnevaluated() {
exists(Element e | e = getParentWithConversions+() | exists(Element e | e = this.getParentWithConversions+() |
e instanceof SizeofOperator e instanceof SizeofOperator
or or
exists(Expr e2 | exists(Expr e2 |
@@ -279,7 +279,7 @@ class Expr extends StmtParent, @expr {
e instanceof AlignofOperator e instanceof AlignofOperator
) )
or or
exists(Decltype d | d.getExpr() = getParentWithConversions*()) exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
} }
/** /**
@@ -725,7 +725,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect {
* *
* Gets the expression that is being dereferenced. * Gets the expression that is being dereferenced.
*/ */
deprecated Expr getExpr() { result = getOperand() } deprecated Expr getExpr() { result = this.getOperand() }
override string getOperator() { result = "*" } override string getOperator() { result = "*" }
@@ -780,15 +780,15 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
* Gets the alignment argument passed to the allocation function, if any. * Gets the alignment argument passed to the allocation function, if any.
*/ */
Expr getAlignmentArgument() { Expr getAlignmentArgument() {
hasAlignedAllocation() and this.hasAlignedAllocation() and
( (
// If we have an allocator call, the alignment is the second argument to // If we have an allocator call, the alignment is the second argument to
// that call. // that call.
result = getAllocatorCall().getArgument(1) result = this.getAllocatorCall().getArgument(1)
or or
// Otherwise, the alignment winds up as child number 3 of the `new` // Otherwise, the alignment winds up as child number 3 of the `new`
// itself. // itself.
result = getChild(3) result = this.getChild(3)
) )
} }
@@ -916,7 +916,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
* Gets the element type of the array being allocated. * Gets the element type of the array being allocated.
*/ */
Type getAllocatedElementType() { Type getAllocatedElementType() {
result = getType().getUnderlyingType().(PointerType).getBaseType() result = this.getType().getUnderlyingType().(PointerType).getBaseType()
} }
/** /**
@@ -946,7 +946,12 @@ class DeleteExpr extends Expr, @delete_expr {
*/ */
Type getDeletedObjectType() { Type getDeletedObjectType() {
result = result =
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() this.getExpr()
.getFullyConverted()
.getType()
.stripTopLevelSpecifiers()
.(PointerType)
.getBaseType()
} }
/** /**
@@ -957,7 +962,7 @@ class DeleteExpr extends Expr, @delete_expr {
/** /**
* Gets the destructor to be called to destroy the object, if any. * Gets the destructor to be called to destroy the object, if any.
*/ */
Destructor getDestructor() { result = getDestructorCall().getTarget() } Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
/** /**
* Gets the `operator delete` that deallocates storage. Does not hold * Gets the `operator delete` that deallocates storage. Does not hold
@@ -1020,7 +1025,12 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
*/ */
Type getDeletedElementType() { Type getDeletedElementType() {
result = result =
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() this.getExpr()
.getFullyConverted()
.getType()
.stripTopLevelSpecifiers()
.(PointerType)
.getBaseType()
} }
/** /**
@@ -1034,7 +1044,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
/** /**
* Gets the destructor to be called to destroy each element in the array, if any. * Gets the destructor to be called to destroy each element in the array, if any.
*/ */
Destructor getDestructor() { result = getDestructorCall().getTarget() } Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
/** /**
* Gets the `operator delete[]` that deallocates storage. * Gets the `operator delete[]` that deallocates storage.
@@ -1101,7 +1111,7 @@ class StmtExpr extends Expr, @expr_stmt {
* x = ({ dosomething(); a+b; }); * x = ({ dosomething(); a+b; });
* ``` * ```
*/ */
Expr getResultExpr() { result = getStmtResultExpr(getStmt()) } Expr getResultExpr() { result = getStmtResultExpr(this.getStmt()) }
} }
/** Get the result expression of a statement. (Helper function for StmtExpr.) */ /** Get the result expression of a statement. (Helper function for StmtExpr.) */
@@ -1230,20 +1240,20 @@ class FoldExpr extends Expr, @foldexpr {
predicate isRightFold() { fold(underlyingElement(this), _, false) } predicate isRightFold() { fold(underlyingElement(this), _, false) }
/** Holds if this is a unary fold expression. */ /** Holds if this is a unary fold expression. */
predicate isUnaryFold() { getNumChild() = 1 } predicate isUnaryFold() { this.getNumChild() = 1 }
/** Holds if this is a binary fold expression. */ /** Holds if this is a binary fold expression. */
predicate isBinaryFold() { getNumChild() = 2 } predicate isBinaryFold() { this.getNumChild() = 2 }
/** /**
* Gets the child expression containing the unexpanded parameter pack. * Gets the child expression containing the unexpanded parameter pack.
*/ */
Expr getPackExpr() { Expr getPackExpr() {
this.isUnaryFold() and this.isUnaryFold() and
result = getChild(0) result = this.getChild(0)
or or
this.isBinaryFold() and this.isBinaryFold() and
if this.isRightFold() then result = getChild(0) else result = getChild(1) if this.isRightFold() then result = this.getChild(0) else result = this.getChild(1)
} }
/** /**
@@ -1251,7 +1261,7 @@ class FoldExpr extends Expr, @foldexpr {
*/ */
Expr getInitExpr() { Expr getInitExpr() {
this.isBinaryFold() and this.isBinaryFold() and
if this.isRightFold() then result = getChild(1) else result = getChild(0) if this.isRightFold() then result = this.getChild(1) else result = this.getChild(0)
} }
} }

View File

@@ -24,7 +24,7 @@ class LambdaExpression extends Expr, @lambdaexpr {
/** /**
* Gets an implicitly or explicitly captured value of this lambda expression. * Gets an implicitly or explicitly captured value of this lambda expression.
*/ */
LambdaCapture getACapture() { result = getCapture(_) } LambdaCapture getACapture() { result = this.getCapture(_) }
/** /**
* Gets the nth implicitly or explicitly captured value of this lambda expression. * Gets the nth implicitly or explicitly captured value of this lambda expression.
@@ -58,13 +58,13 @@ class LambdaExpression extends Expr, @lambdaexpr {
* - The return type. * - The return type.
* - The statements comprising the lambda body. * - The statements comprising the lambda body.
*/ */
Operator getLambdaFunction() { result = getType().(Closure).getLambdaFunction() } Operator getLambdaFunction() { result = this.getType().(Closure).getLambdaFunction() }
/** /**
* Gets the initializer that initializes the captured variables in the closure, if any. * Gets the initializer that initializes the captured variables in the closure, if any.
* A lambda that does not capture any variables will not have an initializer. * A lambda that does not capture any variables will not have an initializer.
*/ */
ClassAggregateLiteral getInitializer() { result = getChild(0) } ClassAggregateLiteral getInitializer() { result = this.getChild(0) }
} }
/** /**
@@ -103,7 +103,7 @@ class Closure extends Class {
* ``` * ```
*/ */
class LambdaCapture extends Locatable, @lambdacapture { class LambdaCapture extends Locatable, @lambdacapture {
override string toString() { result = getField().getName() } override string toString() { result = this.getField().getName() }
override string getAPrimaryQlClass() { result = "LambdaCapture" } override string getAPrimaryQlClass() { result = "LambdaCapture" }

View File

@@ -60,12 +60,12 @@ class TextLiteral extends Literal {
/** Gets a hex escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */ /** Gets a hex escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */
string getAHexEscapeSequence(int occurrence, int offset) { string getAHexEscapeSequence(int occurrence, int offset) {
result = getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset) result = this.getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset)
} }
/** Gets an octal escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */ /** Gets an octal escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */
string getAnOctalEscapeSequence(int occurrence, int offset) { string getAnOctalEscapeSequence(int occurrence, int offset) {
result = getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset) result = this.getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset)
} }
/** /**
@@ -75,27 +75,27 @@ class TextLiteral extends Literal {
string getANonStandardEscapeSequence(int occurrence, int offset) { string getANonStandardEscapeSequence(int occurrence, int offset) {
// Find all single character escape sequences (ignoring the start of octal escape sequences), // Find all single character escape sequences (ignoring the start of octal escape sequences),
// together with anything starting like a hex escape sequence but not followed by a hex digit. // together with anything starting like a hex escape sequence but not followed by a hex digit.
result = getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and result = this.getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and
// From these, exclude all standard escape sequences. // From these, exclude all standard escape sequences.
not result = getAStandardEscapeSequence(_, _) not result = this.getAStandardEscapeSequence(_, _)
} }
/** Gets a simple escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */ /** Gets a simple escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */
string getASimpleEscapeSequence(int occurrence, int offset) { string getASimpleEscapeSequence(int occurrence, int offset) {
result = getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset) result = this.getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset)
} }
/** Gets a standard escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */ /** Gets a standard escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */
string getAStandardEscapeSequence(int occurrence, int offset) { string getAStandardEscapeSequence(int occurrence, int offset) {
result = getASimpleEscapeSequence(occurrence, offset) or result = this.getASimpleEscapeSequence(occurrence, offset) or
result = getAnOctalEscapeSequence(occurrence, offset) or result = this.getAnOctalEscapeSequence(occurrence, offset) or
result = getAHexEscapeSequence(occurrence, offset) result = this.getAHexEscapeSequence(occurrence, offset)
} }
/** /**
* Gets the length of the string literal (including null) before escape sequences added by the extractor. * Gets the length of the string literal (including null) before escape sequences added by the extractor.
*/ */
int getOriginalLength() { result = getValue().length() + 1 } int getOriginalLength() { result = this.getValue().length() + 1 }
} }
/** /**
@@ -216,7 +216,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
( (
// If the field has an explicit initializer expression, then the field is // If the field has an explicit initializer expression, then the field is
// initialized. // initialized.
exists(getFieldExpr(field)) exists(this.getFieldExpr(field))
or or
// If the type is not a union, all fields without initializers are value // If the type is not a union, all fields without initializers are value
// initialized. // initialized.
@@ -224,7 +224,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
or or
// If the type is a union, and there are no explicit initializers, then // If the type is a union, and there are no explicit initializers, then
// the first declared field is value initialized. // the first declared field is value initialized.
not exists(getAChild()) and not exists(this.getAChild()) and
field.getInitializationOrder() = 0 field.getInitializationOrder() = 0
) )
} }
@@ -239,8 +239,8 @@ class ClassAggregateLiteral extends AggregateLiteral {
*/ */
pragma[inline] pragma[inline]
predicate isValueInitialized(Field field) { predicate isValueInitialized(Field field) {
isInitialized(field) and this.isInitialized(field) and
not exists(getFieldExpr(field)) not exists(this.getFieldExpr(field))
} }
} }
@@ -285,7 +285,7 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
bindingset[elementIndex] bindingset[elementIndex]
predicate isInitialized(int elementIndex) { predicate isInitialized(int elementIndex) {
elementIndex >= 0 and elementIndex >= 0 and
elementIndex < getArraySize() elementIndex < this.getArraySize()
} }
/** /**
@@ -298,8 +298,8 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
*/ */
bindingset[elementIndex] bindingset[elementIndex]
predicate isValueInitialized(int elementIndex) { predicate isValueInitialized(int elementIndex) {
isInitialized(elementIndex) and this.isInitialized(elementIndex) and
not exists(getElementExpr(elementIndex)) not exists(this.getElementExpr(elementIndex))
} }
} }

View File

@@ -173,7 +173,7 @@ class LocalVariable extends LocalScopeVariable, @localvariable { }
class VariableDeclarationEntry extends @var_decl { class VariableDeclarationEntry extends @var_decl {
string toString() { result = "QualifiedName DeclarationEntry" } string toString() { result = "QualifiedName DeclarationEntry" }
Variable getDeclaration() { result = getVariable() } Variable getDeclaration() { result = this.getVariable() }
/** /**
* Gets the variable which is being declared or defined. * Gets the variable which is being declared or defined.

View File

@@ -4,7 +4,7 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.DataFlow3 private import semmle.code.cpp.ir.dataflow.DataFlow3
private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch private import semmle.code.cpp.ir.dataflow.ResolveCall
private import semmle.code.cpp.controlflow.IRGuards private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.models.interfaces.Taint private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.DataFlow
@@ -355,20 +355,6 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
*/ */
GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() } GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() }
/**
* Resolve potential target function(s) for `call`.
*
* If `call` is a call through a function pointer (`ExprCall`) or
* targets a virtual method, simple data flow analysis is performed
* in order to identify target(s).
*/
Function resolveCall(Call call) {
exists(CallInstruction callInstruction |
callInstruction.getAST() = call and
result = Dispatch::viableCallable(callInstruction)
)
}
/** /**
* Provides definitions for augmenting source/sink pairs with data-flow paths * Provides definitions for augmenting source/sink pairs with data-flow paths
* between them. From a `@kind path-problem` query, import this module in the * between them. From a `@kind path-problem` query, import this module in the
@@ -479,7 +465,7 @@ module TaintedWithPath {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -0,0 +1,23 @@
/**
* Provides a predicate for non-contextual virtual dispatch and function
* pointer resolution.
*/
import cpp
private import semmle.code.cpp.ir.ValueNumbering
private import internal.DataFlowDispatch
private import semmle.code.cpp.ir.IR
/**
* Resolve potential target function(s) for `call`.
*
* If `call` is a call through a function pointer (`ExprCall`) or its target is
* a virtual member function, simple data flow analysis is performed in order
* to identify the possible target(s).
*/
Function resolveCall(Call call) {
exists(CallInstruction callInstruction |
callInstruction.getAST() = call and
result = viableCallable(callInstruction)
)
}

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowTo(Node sink) { hasFlow(_, sink) } predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/** /**
* Holds if data may flow from some source to `sink` for this configuration. * Holds if data may flow from some source to `sink` for this configuration.
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/** /**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
} }
int getPosition() { this.isParameterOf(_, result) } int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
} }
private class RetNodeEx extends NodeEx { private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
exists(ap) and exists(ap) and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() (
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and ) and
accessPathApproxCostLimits(apLimit, tupleLimit) and accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and apLimit < tails and
tupleLimit < (tails - 1) * nodes tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
) )
} }
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and kind = ret.getKind() and
p.getPosition() = pos and p.getPosition() = pos and
// we don't expect a parameter to return stored in itself // we don't expect a parameter to return stored in itself, unless explicitly allowed
not kind.(ParamUpdateReturnKind).getPosition() = pos (
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
) )
} }
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) } int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap } override string toString() { result = p + ": " + ap }
predicate hasLocationInfo( predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise. * expected to be expensive. Holds with `unfold = true` otherwise.
*/ */
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit | if apa.getHead().forceHighPrecision()
aps = countPotentialAps(apa, config) and then unfold = true
nodes = countNodesUsingAccessPath(apa, config) and else
accessPathCostLimits(apLimit, tupleLimit) and exists(int aps, int nodes, int apLimit, int tupleLimit |
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true aps = countPotentialAps(apa, config) and
) nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
} }
/** /**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
} }
override string toString() { override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]" result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or or
result = "[" + this.toStringImpl(false) result = "[" + this.toStringImpl(false)
} }
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
} }
override string toString() { result = this.getNodeEx().toString() + ppAp() } override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() } override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() { override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node // an intermediate step to another intermediate node
result = getSuccMid() result = this.getSuccMid()
or or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink | exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx() sc = mid.getSummaryCtx()
or or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp() pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/ */
pragma[noinline] pragma[noinline]
private predicate pathIntoArg( private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) { ) {
exists(ArgNode arg | exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
arg.argumentOf(call, i) and arg.argumentOf(call, i) and
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() apa = ap.getApprox() and
config = mid.getConfiguration()
) )
} }
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic] pragma[nomagic]
private predicate pathIntoCallable0( private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call, PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap AccessPath ap, Configuration config
) { ) {
exists(AccessPathApprox apa | exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration()) parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
) )
} }
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`, * before and after entering the callable are `outercc` and `innercc`,
* respectively. * respectively.
*/ */
pragma[nomagic]
private predicate pathIntoCallable( private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc, PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call DataFlowCall call, Configuration config
) { ) {
exists(int i, DataFlowCallable callable, AccessPath ap | exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and p.isParameterOf(callable, i) and
( (
sc = TSummaryCtxSome(p, ap) sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and ap = mid.getAp() and
apa = ap.getApprox() and apa = ap.getApprox() and
pos = sc.getParameterPos() and pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos // we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
) )
} }
pragma[nomagic] pragma[nomagic]
private predicate pathThroughCallable0( private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap, DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa AccessPathApprox apa, Configuration config
) { ) {
exists(CallContext innercc, SummaryCtx sc | exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration())) paramFlowsThrough(kind, innercc, sc, ap, apa, config)
) )
} }
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/ */
pragma[noinline] pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) { private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration())) out = getAnOutNodeFlow(kind, call, apa, config)
) )
} }
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout NodeEx out, AccessPath apout
) { ) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and exists(Configuration config |
pathIntoCallable(arg, par, _, innercc, sc, _) and pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, pathIntoCallable(arg, par, _, innercc, sc, _, config) and
unbindConf(arg.getConfiguration())) paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
} }
/** /**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -801,6 +801,9 @@ private module Cached {
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
} }
cached
predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) }
cached cached
newtype TCallContext = newtype TCallContext =
TAnyCallContext() or TAnyCallContext() or
@@ -937,7 +940,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
} }
override predicate relevantFor(DataFlowCallable callable) { override predicate relevantFor(DataFlowCallable callable) {
recordDataFlowCallSite(getCall(), callable) recordDataFlowCallSite(this.getCall(), callable)
} }
override predicate matchesCall(DataFlowCall call) { call = this.getCall() } override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
@@ -1236,6 +1239,13 @@ class TypedContent extends MkTypedContent {
/** Gets a textual representation of this content. */ /** Gets a textual representation of this content. */
string toString() { result = c.toString() } string toString() { result = c.toString() }
/**
* Holds if access paths with this `TypedContent` at their head always should
* be tracked at high precision. This disables adaptive access path precision
* for such access paths.
*/
predicate forceHighPrecision() { forceHighPrecision(c) }
} }
/** /**
@@ -1250,7 +1260,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) } TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) } predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
} }
class AccessPathFrontNil extends AccessPathFront, TFrontNil { class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -175,6 +175,7 @@ module Consistency {
query predicate postWithInFlow(Node n, string msg) { query predicate postWithInFlow(Node n, string msg) {
isPostUpdateNode(n) and isPostUpdateNode(n) and
not clearsContent(n, _) and
simpleLocalFlowStep(_, n) and simpleLocalFlowStep(_, n) and
msg = "PostUpdateNode should not be the target of local flow." msg = "PostUpdateNode should not be the target of local flow."
} }

View File

@@ -466,6 +466,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl
int accessPathLimit() { result = 5 } int accessPathLimit() { result = 5 }
/**
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) { none() }
/** The unit type. */ /** The unit type. */
private newtype TUnit = TMkUnit() private newtype TUnit = TMkUnit()
@@ -501,3 +507,12 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
/** Extra data-flow steps needed for lambda flow analysis. */ /** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.
*
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p) { none() }

View File

@@ -110,7 +110,7 @@ class Node extends TIRDataFlowNode {
/** /**
* Gets an upper bound on the type of this node. * Gets an upper bound on the type of this node.
*/ */
IRType getTypeBound() { result = getType() } IRType getTypeBound() { result = this.getType() }
/** Gets the location of this element. */ /** Gets the location of this element. */
Location getLocation() { none() } // overridden by subclasses Location getLocation() { none() } // overridden by subclasses
@@ -120,7 +120,7 @@ class Node extends TIRDataFlowNode {
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/ */
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -831,7 +831,7 @@ class FieldContent extends Content, TFieldContent {
FieldContent() { this = TFieldContent(c, startBit, endBit) } FieldContent() { this = TFieldContent(c, startBit, endBit) }
// Ensure that there's just 1 result for `toString`. // Ensure that there's just 1 result for `toString`.
override string toString() { result = min(Field f | f = getAField() | f.toString()) } override string toString() { result = min(Field f | f = this.getAField() | f.toString()) }
predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit } predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit }

View File

@@ -38,5 +38,8 @@ Instruction callOutput(CallInstruction call, FunctionOutput output) {
effect.getPrimaryInstruction() = call and effect.getPrimaryInstruction() = call and
output.isParameterDerefOrQualifierObject(effect.getIndex()) output.isParameterDerefOrQualifierObject(effect.getIndex())
) )
// TODO: return value dereference or
// TODO: modify this when we get return value dereferences
result = call and
output.isReturnValueDeref()
} }

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or this.isSanitizer(node) or
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() } predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or this.isSanitizer(node) or
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() } predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or this.isSanitizer(node) or
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() } predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) } final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }

View File

@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
final string toString() { result = getFirstInstruction(this).toString() } final string toString() { result = getFirstInstruction(this).toString() }
/** Gets the source location of the first non-`Phi` instruction in this block. */ /** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() } final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
/** /**
* INTERNAL: Do not use. * INTERNAL: Do not use.
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
) and ) and
this = this =
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first. // Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
* Get the `Phi` instructions that appear at the start of this block. * Get the `Phi` instructions that appear at the start of this block.
*/ */
final PhiInstruction getAPhiInstruction() { final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
} }
/** /**
* Gets an instruction in this block. This includes `Phi` instructions. * Gets an instruction in this block. This includes `Phi` instructions.
*/ */
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
result = getInstruction(_) or result = this.getInstruction(_) or
result = getAPhiInstruction() result = this.getAPhiInstruction()
} }
/** /**
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
/** /**
* Gets the last instruction in this block. * Gets the last instruction in this block.
*/ */
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } final Instruction getLastInstruction() {
result = this.getInstruction(this.getInstructionCount() - 1)
}
/** /**
* Gets the number of non-`Phi` instructions in this block. * Gets the number of non-`Phi` instructions in this block.
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
* Block `A` dominates block `B` if any control flow path from the entry block of the function to * Block `A` dominates block `B` if any control flow path from the entry block of the function to
* block `B` must pass through block `A`. A block always dominates itself. * block `B` must pass through block `A`. A block always dominates itself.
*/ */
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
/** /**
* Gets a block on the dominance frontier of this block. * Gets a block on the dominance frontier of this block.
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
*/ */
pragma[noinline] pragma[noinline]
final IRBlock dominanceFrontier() { final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and this.dominates(result.getAPredecessor()) and
not strictlyDominates(result) not this.strictlyDominates(result)
} }
/** /**
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
* function must pass through block `A`. A block always post-dominates itself. * function must pass through block `A`. A block always post-dominates itself.
*/ */
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
/** /**
* Gets a block on the post-dominance frontier of this block. * Gets a block on the post-dominance frontier of this block.
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
*/ */
pragma[noinline] pragma[noinline]
final IRBlock postPominanceFrontier() { final IRBlock postPominanceFrontier() {
postDominates(result.getASuccessor()) and this.postDominates(result.getASuccessor()) and
not strictlyPostDominates(result) not this.strictlyPostDominates(result)
} }
/** /**
* Holds if this block is reachable from the entry block of its function. * Holds if this block is reachable from the entry block of its function.
*/ */
final predicate isReachableFromFunctionEntry() { final predicate isReachableFromFunctionEntry() {
this = getEnclosingIRFunction().getEntryBlock() or this = this.getEnclosingIRFunction().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry() this.getAPredecessor().isReachableFromFunctionEntry()
} }
} }

View File

@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
/** /**
* Gets the location of the source code for this operand. * Gets the location of the source code for this operand.
*/ */
final Language::Location getLocation() { result = getUse().getLocation() } final Language::Location getLocation() { result = this.getUse().getLocation() }
/** /**
* Gets the function that contains this operand. * Gets the function that contains this operand.
*/ */
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
/** /**
* Gets the `Instruction` that consumes this operand. * Gets the `Instruction` that consumes this operand.
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
*/ */
final Instruction getDef() { final Instruction getDef() {
result = this.getAnyDef() and result = this.getAnyDef() and
getDefinitionOverlap() instanceof MustExactlyOverlap this.getDefinitionOverlap() instanceof MustExactlyOverlap
} }
/** /**
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
* *
* Gets the `Instruction` that consumes this operand. * Gets the `Instruction` that consumes this operand.
*/ */
deprecated final Instruction getUseInstruction() { result = getUse() } deprecated final Instruction getUseInstruction() { result = this.getUse() }
/** /**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
* *
* Gets the `Instruction` whose result is the value of the operand. * Gets the `Instruction` whose result is the value of the operand.
*/ */
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
/** /**
* Gets the overlap relationship between the operand's definition and its use. * Gets the overlap relationship between the operand's definition and its use.
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
/** /**
* Holds if the result of the definition instruction does not exactly overlap this use. * Holds if the result of the definition instruction does not exactly overlap this use.
*/ */
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } final predicate isDefinitionInexact() {
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
}
/** /**
* Gets a prefix to use when dumping the operand in an operand list. * Gets a prefix to use when dumping the operand in an operand list.
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
* For example: `this:r3_5` * For example: `this:r3_5`
*/ */
final string getDumpString() { final string getDumpString() {
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
} }
/** /**
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
* definition is not modeled in SSA. * definition is not modeled in SSA.
*/ */
private string getDefinitionId() { private string getDefinitionId() {
result = getAnyDef().getResultId() result = this.getAnyDef().getResultId()
or or
not exists(getAnyDef()) and result = "m?" not exists(this.getAnyDef()) and result = "m?"
} }
/** /**
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
* the empty string. * the empty string.
*/ */
private string getInexactSpecifier() { private string getInexactSpecifier() {
if isDefinitionInexact() then result = "~" else result = "" if this.isDefinitionInexact() then result = "~" else result = ""
} }
/** /**
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that * the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
/** /**
* Gets the language-neutral type of the value consumed by this operand. This is usually the same * Gets the language-neutral type of the value consumed by this operand. This is usually the same
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
* from the definition type, such as in the case of a partial read or a read from a pointer that * from the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
final IRType getIRType() { result = getLanguageType().getIRType() } final IRType getIRType() { result = this.getLanguageType().getIRType() }
/** /**
* Gets the type of the value consumed by this operand. This is usually the same as the * Gets the type of the value consumed by this operand. This is usually the same as the
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that * the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
final Language::Type getType() { getLanguageType().hasType(result, _) } final Language::Type getType() { this.getLanguageType().hasType(result, _) }
/** /**
* Holds if the value consumed by this operand is a glvalue. If this * Holds if the value consumed by this operand is a glvalue. If this
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
* not hold, the value of the operand represents a value whose type is * not hold, the value of the operand represents a value whose type is
* given by `getType()`. * given by `getType()`.
*/ */
final predicate isGLValue() { getLanguageType().hasType(_, true) } final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
/** /**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have * Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold. * a known constant size, this predicate does not hold.
*/ */
final int getSize() { result = getLanguageType().getByteSize() } final int getSize() { result = this.getLanguageType().getByteSize() }
} }
/** /**
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
/** /**
* Gets the kind of memory access performed by the operand. * Gets the kind of memory access performed by the operand.
*/ */
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
/** /**
* Holds if the memory access performed by this operand will not always read from every bit in the * Holds if the memory access performed by this operand will not always read from every bit in the
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example, * conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call). * the global side effects of a function call).
*/ */
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
/** /**
* Returns the operand that holds the memory address from which the current operand loads its * Returns the operand that holds the memory address from which the current operand loads its
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
* is `r1`. * is `r1`.
*/ */
final AddressOperand getAddressOperand() { final AddressOperand getAddressOperand() {
getMemoryAccess().usesAddressOperand() and this.getMemoryAccess().usesAddressOperand() and
result.getUse() = getUse() result.getUse() = this.getUse()
} }
} }
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
result = unique(Instruction defInstr | hasDefinition(defInstr, _)) result = unique(Instruction defInstr | hasDefinition(defInstr, _))
} }
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
pragma[noinline] pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) { private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
final override Overlap getDefinitionOverlap() { result = overlap } final override Overlap getDefinitionOverlap() { result = overlap }
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } final override int getDumpSortOrder() {
result = 11 + this.getPredecessorBlock().getDisplayIndex()
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
} }
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } final override string getDumpLabel() {
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
}
final override string getDumpId() {
result = this.getPredecessorBlock().getDisplayIndex().toString()
}
/** /**
* Gets the predecessor block from which this value comes. * Gets the predecessor block from which this value comes.

View File

@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
final string toString() { result = getFirstInstruction(this).toString() } final string toString() { result = getFirstInstruction(this).toString() }
/** Gets the source location of the first non-`Phi` instruction in this block. */ /** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() } final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
/** /**
* INTERNAL: Do not use. * INTERNAL: Do not use.
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
) and ) and
this = this =
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first. // Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
* Get the `Phi` instructions that appear at the start of this block. * Get the `Phi` instructions that appear at the start of this block.
*/ */
final PhiInstruction getAPhiInstruction() { final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
} }
/** /**
* Gets an instruction in this block. This includes `Phi` instructions. * Gets an instruction in this block. This includes `Phi` instructions.
*/ */
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
result = getInstruction(_) or result = this.getInstruction(_) or
result = getAPhiInstruction() result = this.getAPhiInstruction()
} }
/** /**
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
/** /**
* Gets the last instruction in this block. * Gets the last instruction in this block.
*/ */
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } final Instruction getLastInstruction() {
result = this.getInstruction(this.getInstructionCount() - 1)
}
/** /**
* Gets the number of non-`Phi` instructions in this block. * Gets the number of non-`Phi` instructions in this block.
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
* Block `A` dominates block `B` if any control flow path from the entry block of the function to * Block `A` dominates block `B` if any control flow path from the entry block of the function to
* block `B` must pass through block `A`. A block always dominates itself. * block `B` must pass through block `A`. A block always dominates itself.
*/ */
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
/** /**
* Gets a block on the dominance frontier of this block. * Gets a block on the dominance frontier of this block.
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
*/ */
pragma[noinline] pragma[noinline]
final IRBlock dominanceFrontier() { final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and this.dominates(result.getAPredecessor()) and
not strictlyDominates(result) not this.strictlyDominates(result)
} }
/** /**
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
* function must pass through block `A`. A block always post-dominates itself. * function must pass through block `A`. A block always post-dominates itself.
*/ */
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
/** /**
* Gets a block on the post-dominance frontier of this block. * Gets a block on the post-dominance frontier of this block.
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
*/ */
pragma[noinline] pragma[noinline]
final IRBlock postPominanceFrontier() { final IRBlock postPominanceFrontier() {
postDominates(result.getASuccessor()) and this.postDominates(result.getASuccessor()) and
not strictlyPostDominates(result) not this.strictlyPostDominates(result)
} }
/** /**
* Holds if this block is reachable from the entry block of its function. * Holds if this block is reachable from the entry block of its function.
*/ */
final predicate isReachableFromFunctionEntry() { final predicate isReachableFromFunctionEntry() {
this = getEnclosingIRFunction().getEntryBlock() or this = this.getEnclosingIRFunction().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry() this.getAPredecessor().isReachableFromFunctionEntry()
} }
} }

View File

@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
/** /**
* Gets the location of the source code for this operand. * Gets the location of the source code for this operand.
*/ */
final Language::Location getLocation() { result = getUse().getLocation() } final Language::Location getLocation() { result = this.getUse().getLocation() }
/** /**
* Gets the function that contains this operand. * Gets the function that contains this operand.
*/ */
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
/** /**
* Gets the `Instruction` that consumes this operand. * Gets the `Instruction` that consumes this operand.
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
*/ */
final Instruction getDef() { final Instruction getDef() {
result = this.getAnyDef() and result = this.getAnyDef() and
getDefinitionOverlap() instanceof MustExactlyOverlap this.getDefinitionOverlap() instanceof MustExactlyOverlap
} }
/** /**
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
* *
* Gets the `Instruction` that consumes this operand. * Gets the `Instruction` that consumes this operand.
*/ */
deprecated final Instruction getUseInstruction() { result = getUse() } deprecated final Instruction getUseInstruction() { result = this.getUse() }
/** /**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
* *
* Gets the `Instruction` whose result is the value of the operand. * Gets the `Instruction` whose result is the value of the operand.
*/ */
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
/** /**
* Gets the overlap relationship between the operand's definition and its use. * Gets the overlap relationship between the operand's definition and its use.
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
/** /**
* Holds if the result of the definition instruction does not exactly overlap this use. * Holds if the result of the definition instruction does not exactly overlap this use.
*/ */
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } final predicate isDefinitionInexact() {
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
}
/** /**
* Gets a prefix to use when dumping the operand in an operand list. * Gets a prefix to use when dumping the operand in an operand list.
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
* For example: `this:r3_5` * For example: `this:r3_5`
*/ */
final string getDumpString() { final string getDumpString() {
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
} }
/** /**
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
* definition is not modeled in SSA. * definition is not modeled in SSA.
*/ */
private string getDefinitionId() { private string getDefinitionId() {
result = getAnyDef().getResultId() result = this.getAnyDef().getResultId()
or or
not exists(getAnyDef()) and result = "m?" not exists(this.getAnyDef()) and result = "m?"
} }
/** /**
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
* the empty string. * the empty string.
*/ */
private string getInexactSpecifier() { private string getInexactSpecifier() {
if isDefinitionInexact() then result = "~" else result = "" if this.isDefinitionInexact() then result = "~" else result = ""
} }
/** /**
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that * the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
/** /**
* Gets the language-neutral type of the value consumed by this operand. This is usually the same * Gets the language-neutral type of the value consumed by this operand. This is usually the same
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
* from the definition type, such as in the case of a partial read or a read from a pointer that * from the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
final IRType getIRType() { result = getLanguageType().getIRType() } final IRType getIRType() { result = this.getLanguageType().getIRType() }
/** /**
* Gets the type of the value consumed by this operand. This is usually the same as the * Gets the type of the value consumed by this operand. This is usually the same as the
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that * the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
final Language::Type getType() { getLanguageType().hasType(result, _) } final Language::Type getType() { this.getLanguageType().hasType(result, _) }
/** /**
* Holds if the value consumed by this operand is a glvalue. If this * Holds if the value consumed by this operand is a glvalue. If this
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
* not hold, the value of the operand represents a value whose type is * not hold, the value of the operand represents a value whose type is
* given by `getType()`. * given by `getType()`.
*/ */
final predicate isGLValue() { getLanguageType().hasType(_, true) } final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
/** /**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have * Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold. * a known constant size, this predicate does not hold.
*/ */
final int getSize() { result = getLanguageType().getByteSize() } final int getSize() { result = this.getLanguageType().getByteSize() }
} }
/** /**
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
/** /**
* Gets the kind of memory access performed by the operand. * Gets the kind of memory access performed by the operand.
*/ */
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
/** /**
* Holds if the memory access performed by this operand will not always read from every bit in the * Holds if the memory access performed by this operand will not always read from every bit in the
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example, * conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call). * the global side effects of a function call).
*/ */
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
/** /**
* Returns the operand that holds the memory address from which the current operand loads its * Returns the operand that holds the memory address from which the current operand loads its
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
* is `r1`. * is `r1`.
*/ */
final AddressOperand getAddressOperand() { final AddressOperand getAddressOperand() {
getMemoryAccess().usesAddressOperand() and this.getMemoryAccess().usesAddressOperand() and
result.getUse() = getUse() result.getUse() = this.getUse()
} }
} }
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
result = unique(Instruction defInstr | hasDefinition(defInstr, _)) result = unique(Instruction defInstr | hasDefinition(defInstr, _))
} }
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
pragma[noinline] pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) { private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
final override Overlap getDefinitionOverlap() { result = overlap } final override Overlap getDefinitionOverlap() { result = overlap }
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } final override int getDumpSortOrder() {
result = 11 + this.getPredecessorBlock().getDisplayIndex()
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
} }
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } final override string getDumpLabel() {
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
}
final override string getDumpId() {
result = this.getPredecessorBlock().getDisplayIndex().toString()
}
/** /**
* Gets the predecessor block from which this value comes. * Gets the predecessor block from which this value comes.

View File

@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
final string toString() { result = getFirstInstruction(this).toString() } final string toString() { result = getFirstInstruction(this).toString() }
/** Gets the source location of the first non-`Phi` instruction in this block. */ /** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() } final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
/** /**
* INTERNAL: Do not use. * INTERNAL: Do not use.
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
) and ) and
this = this =
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first. // Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
* Get the `Phi` instructions that appear at the start of this block. * Get the `Phi` instructions that appear at the start of this block.
*/ */
final PhiInstruction getAPhiInstruction() { final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction() Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
} }
/** /**
* Gets an instruction in this block. This includes `Phi` instructions. * Gets an instruction in this block. This includes `Phi` instructions.
*/ */
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
result = getInstruction(_) or result = this.getInstruction(_) or
result = getAPhiInstruction() result = this.getAPhiInstruction()
} }
/** /**
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
/** /**
* Gets the last instruction in this block. * Gets the last instruction in this block.
*/ */
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) } final Instruction getLastInstruction() {
result = this.getInstruction(this.getInstructionCount() - 1)
}
/** /**
* Gets the number of non-`Phi` instructions in this block. * Gets the number of non-`Phi` instructions in this block.
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
* Block `A` dominates block `B` if any control flow path from the entry block of the function to * Block `A` dominates block `B` if any control flow path from the entry block of the function to
* block `B` must pass through block `A`. A block always dominates itself. * block `B` must pass through block `A`. A block always dominates itself.
*/ */
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block } final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
/** /**
* Gets a block on the dominance frontier of this block. * Gets a block on the dominance frontier of this block.
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
*/ */
pragma[noinline] pragma[noinline]
final IRBlock dominanceFrontier() { final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and this.dominates(result.getAPredecessor()) and
not strictlyDominates(result) not this.strictlyDominates(result)
} }
/** /**
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the * Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
* function must pass through block `A`. A block always post-dominates itself. * function must pass through block `A`. A block always post-dominates itself.
*/ */
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block } final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
/** /**
* Gets a block on the post-dominance frontier of this block. * Gets a block on the post-dominance frontier of this block.
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
*/ */
pragma[noinline] pragma[noinline]
final IRBlock postPominanceFrontier() { final IRBlock postPominanceFrontier() {
postDominates(result.getASuccessor()) and this.postDominates(result.getASuccessor()) and
not strictlyPostDominates(result) not this.strictlyPostDominates(result)
} }
/** /**
* Holds if this block is reachable from the entry block of its function. * Holds if this block is reachable from the entry block of its function.
*/ */
final predicate isReachableFromFunctionEntry() { final predicate isReachableFromFunctionEntry() {
this = getEnclosingIRFunction().getEntryBlock() or this = this.getEnclosingIRFunction().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry() this.getAPredecessor().isReachableFromFunctionEntry()
} }
} }

View File

@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
/** /**
* Gets the location of the source code for this operand. * Gets the location of the source code for this operand.
*/ */
final Language::Location getLocation() { result = getUse().getLocation() } final Language::Location getLocation() { result = this.getUse().getLocation() }
/** /**
* Gets the function that contains this operand. * Gets the function that contains this operand.
*/ */
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() } final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
/** /**
* Gets the `Instruction` that consumes this operand. * Gets the `Instruction` that consumes this operand.
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
*/ */
final Instruction getDef() { final Instruction getDef() {
result = this.getAnyDef() and result = this.getAnyDef() and
getDefinitionOverlap() instanceof MustExactlyOverlap this.getDefinitionOverlap() instanceof MustExactlyOverlap
} }
/** /**
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
* *
* Gets the `Instruction` that consumes this operand. * Gets the `Instruction` that consumes this operand.
*/ */
deprecated final Instruction getUseInstruction() { result = getUse() } deprecated final Instruction getUseInstruction() { result = this.getUse() }
/** /**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
* *
* Gets the `Instruction` whose result is the value of the operand. * Gets the `Instruction` whose result is the value of the operand.
*/ */
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() } deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
/** /**
* Gets the overlap relationship between the operand's definition and its use. * Gets the overlap relationship between the operand's definition and its use.
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
/** /**
* Holds if the result of the definition instruction does not exactly overlap this use. * Holds if the result of the definition instruction does not exactly overlap this use.
*/ */
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap } final predicate isDefinitionInexact() {
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
}
/** /**
* Gets a prefix to use when dumping the operand in an operand list. * Gets a prefix to use when dumping the operand in an operand list.
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
* For example: `this:r3_5` * For example: `this:r3_5`
*/ */
final string getDumpString() { final string getDumpString() {
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId() result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
} }
/** /**
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
* definition is not modeled in SSA. * definition is not modeled in SSA.
*/ */
private string getDefinitionId() { private string getDefinitionId() {
result = getAnyDef().getResultId() result = this.getAnyDef().getResultId()
or or
not exists(getAnyDef()) and result = "m?" not exists(this.getAnyDef()) and result = "m?"
} }
/** /**
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
* the empty string. * the empty string.
*/ */
private string getInexactSpecifier() { private string getInexactSpecifier() {
if isDefinitionInexact() then result = "~" else result = "" if this.isDefinitionInexact() then result = "~" else result = ""
} }
/** /**
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that * the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() } Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
/** /**
* Gets the language-neutral type of the value consumed by this operand. This is usually the same * Gets the language-neutral type of the value consumed by this operand. This is usually the same
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
* from the definition type, such as in the case of a partial read or a read from a pointer that * from the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
final IRType getIRType() { result = getLanguageType().getIRType() } final IRType getIRType() { result = this.getLanguageType().getIRType() }
/** /**
* Gets the type of the value consumed by this operand. This is usually the same as the * Gets the type of the value consumed by this operand. This is usually the same as the
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that * the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type. * has been cast to a different type.
*/ */
final Language::Type getType() { getLanguageType().hasType(result, _) } final Language::Type getType() { this.getLanguageType().hasType(result, _) }
/** /**
* Holds if the value consumed by this operand is a glvalue. If this * Holds if the value consumed by this operand is a glvalue. If this
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
* not hold, the value of the operand represents a value whose type is * not hold, the value of the operand represents a value whose type is
* given by `getType()`. * given by `getType()`.
*/ */
final predicate isGLValue() { getLanguageType().hasType(_, true) } final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
/** /**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have * Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold. * a known constant size, this predicate does not hold.
*/ */
final int getSize() { result = getLanguageType().getByteSize() } final int getSize() { result = this.getLanguageType().getByteSize() }
} }
/** /**
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
/** /**
* Gets the kind of memory access performed by the operand. * Gets the kind of memory access performed by the operand.
*/ */
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() } MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
/** /**
* Holds if the memory access performed by this operand will not always read from every bit in the * Holds if the memory access performed by this operand will not always read from every bit in the
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example, * conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call). * the global side effects of a function call).
*/ */
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() } predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
/** /**
* Returns the operand that holds the memory address from which the current operand loads its * Returns the operand that holds the memory address from which the current operand loads its
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
* is `r1`. * is `r1`.
*/ */
final AddressOperand getAddressOperand() { final AddressOperand getAddressOperand() {
getMemoryAccess().usesAddressOperand() and this.getMemoryAccess().usesAddressOperand() and
result.getUse() = getUse() result.getUse() = this.getUse()
} }
} }
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
result = unique(Instruction defInstr | hasDefinition(defInstr, _)) result = unique(Instruction defInstr | hasDefinition(defInstr, _))
} }
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) } final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
pragma[noinline] pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) { private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
final override Overlap getDefinitionOverlap() { result = overlap } final override Overlap getDefinitionOverlap() { result = overlap }
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() } final override int getDumpSortOrder() {
result = 11 + this.getPredecessorBlock().getDisplayIndex()
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
} }
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() } final override string getDumpLabel() {
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
}
final override string getDumpId() {
result = this.getPredecessorBlock().getDisplayIndex().toString()
}
/** /**
* Gets the predecessor block from which this value comes. * Gets the predecessor block from which this value comes.

View File

@@ -18,10 +18,11 @@ Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntVal
else else
if isLE(defStart, useStart) and isGE(defEnd, useEnd) if isLE(defStart, useStart) and isGE(defEnd, useEnd)
then result instanceof MustTotallyOverlap then result instanceof MustTotallyOverlap
else else (
if isLE(defEnd, useStart) or isGE(defStart, useEnd) not isLE(defEnd, useStart) and
then none() not isGE(defStart, useEnd) and
else result instanceof MayPartiallyOverlap result instanceof MayPartiallyOverlap
)
} }
/** /**

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