Compare commits

...

693 Commits

Author SHA1 Message Date
Chuan-kai Lin
839ca60f90 Merge pull request #16099 from github/release-prep/2.17.0
Release preparation for version 2.17.0
2024-04-02 11:07:43 -07:00
github-actions[bot]
c511de2eae Release preparation for version 2.17.0 2024-04-02 17:15:41 +00:00
Chuan-kai Lin
b87cf3c41a Merge pull request #16098 from github/revert-16085-release-prep/2.17.0
Revert "Release preparation for version 2.17.0"
2024-04-02 10:11:15 -07:00
Chuan-kai Lin
6c649c898e Revert "Release preparation for version 2.17.0" 2024-04-02 10:06:20 -07:00
Michael B. Gale
48f93438d8 Merge pull request #16096 from github/mbg/go/revert-auto-version-fixing
Go: Revert `go version` call in `LoadGoModules`
2024-04-02 16:01:45 +01:00
Michael B. Gale
55fa245194 Go: Revert go version call in LoadGoModules 2024-04-02 15:20:56 +01:00
Chuan-kai Lin
6475034b09 Merge pull request #16085 from github/release-prep/2.17.0
Release preparation for version 2.17.0
2024-04-01 06:53:52 -07:00
github-actions[bot]
ec97d9a304 Release preparation for version 2.17.0 2024-04-01 13:46:57 +00:00
Jami
d889e3cf98 Merge pull request #14854 from jcogs33/jcogs33/unsafe-url-forward-promotion
Java: Promote Unsafe URL Forward query from experimental
2024-03-29 16:34:06 -04:00
Jami
2f8c4df309 docs wording updates
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-03-28 16:15:05 -04:00
James Fletcher
5b1cae5fc2 Merge pull request #16076 from github/jf205-patch-1
Make customizing-library-models-for-javascript.rst visible to search and the docs TOC
2024-03-28 17:05:32 +00:00
Calum Grant
ef2e2e4067 Merge pull request #16071 from github/calumgrant/cpp-analysis
Add C++ analysis in separate workflow
2024-03-28 17:53:53 +01:00
Michael B. Gale
73f71d8ace Merge pull request #15979 from github/mbg/go/deal-with-incorrect-versions 2024-03-28 14:16:14 +00:00
Michael B. Gale
f6c22d466f Update toolchain_test.go
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-03-28 13:32:02 +00:00
Sid Shankar
aeacfb82c1 Merge pull request #16073 from hmac/ruby-re-add-mad-docs
Ruby: Re-add MaD docs
2024-03-28 09:18:04 -04:00
Paolo Tranquilli
2fa2a5a53c Merge pull request #15984 from github/alexdenisov/swift-5.10
Swift: upgrade to 5.10
2024-03-28 13:58:39 +01:00
Michael B. Gale
977ac71b26 Update toolchain_test.go
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-03-28 11:15:30 +00:00
Ian Lynagh
5dcd635403 Merge pull request #15961 from igfoo/igfoo/MissingEnumInSwitch
Java: Limit the amount of results that MissingEnumInSwitch produces per switch
2024-03-28 11:13:45 +00:00
Paolo Tranquilli
a34bb2608d Swift: fix ql format 2024-03-28 11:57:33 +01:00
Paolo Tranquilli
ece0d1f477 Swift: add upgrade/downgrade scripts 2024-03-28 11:54:18 +01:00
Paolo Tranquilli
bfce01cef6 Swift: add change note for Swift 5.10 upgrade 2024-03-28 11:38:39 +01:00
James Fletcher
d57e8efaf2 Update codeql-for-javascript.rst 2024-03-28 10:28:37 +00:00
Jeroen Ketema
3d8ac1441a Merge pull request #16074 from jketema/reuse-val-cat
C++: Add value category column to the expr_reuse relation
2024-03-28 10:14:32 +01:00
Jeroen Ketema
9eb51a9b9e C++: Add value category column to the expr_reuse relation 2024-03-27 22:49:40 +01:00
Jeroen Ketema
9e47909208 Merge pull request #16065 from geoffw0/codeowners
C++: Divide CODEOWNERS responsibilities.
2024-03-27 22:22:15 +01:00
Harry Maclean
3690f294da Ruby: add MaD doc to TOC tree 2024-03-27 21:02:25 +00:00
Ian Lynagh
b6a1266ade Java: Accept test changes for MissingEnumInSwitch Oxford commas 2024-03-27 18:48:22 +00:00
Harry Maclean
ce0edcc265 Ruby: Make MaD doc visible to search
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2024-03-27 17:29:18 +00:00
James Fletcher
04edd6ec69 Update docs/codeql/codeql-language-guides/codeql-for-javascript.rst 2024-03-27 17:08:47 +00:00
James Fletcher
121fed63a0 Update codeql-for-javascript.rst 2024-03-27 17:06:31 +00:00
James Fletcher
fbc0f57280 Update customizing-library-models-for-javascript.rst 2024-03-27 16:58:11 +00:00
Paolo Tranquilli
e9957aa4a6 Swift: make result a child in ThenStmt 2024-03-27 17:53:36 +01:00
Harry Maclean
f6e2e1319b Ruby: Link to MaD docs from Ruby doc page
Also remove an internal link from the docs.
2024-03-27 15:30:05 +00:00
Harry Maclean
e6ba0a34f4 Revert "Ruby: remove customizing-library-models-for-ruby.rst"
This reverts commit 5b46256fdb.
2024-03-27 15:24:30 +00:00
Michael B. Gale
45b41bb506 Go: Mirror stdout/stderr output in InstallVersion 2024-03-27 15:18:24 +00:00
Michael B. Gale
6b1d1d427c Go: Add integration test for incorrect version format logic 2024-03-27 15:16:32 +00:00
Michael B. Gale
6ea99825be Go: Add unit test to sanity check HasGoVersion 2024-03-27 15:15:40 +00:00
Michael B. Gale
ab255d70b5 Go: Fix semver-related logic bugs 2024-03-27 15:15:20 +00:00
Ian Lynagh
fda3c92612 Java: Add a changenote for the MissingEnumInSwitch change 2024-03-27 15:12:55 +00:00
Ian Lynagh
59ae6dd5f5 Java: Add a couple of Oxford commas 2024-03-27 15:07:58 +00:00
Michael B. Gale
86bf4fbbc0 Go: Make diagnostic names static 2024-03-27 14:22:58 +00:00
Jami Cogswell
40c932a5f9 Java: move UrlForward.qll code to UrlForwardQuery.qll 2024-03-27 10:12:28 -04:00
Max Schaefer
5b07e14fb3 Merge pull request #16055 from github/max-schaefer/go-open-redirect-qhelp
Go: Improve QHelp for `go/unvalidated-url-redirection`.
2024-03-27 13:56:48 +00:00
Paolo Tranquilli
0243d9f2b9 Swift: accept explicit any in existential type name 2024-03-27 13:49:15 +01:00
Jami Cogswell
2391fe7d89 Java: use InlineFlowTest instead of InlineExpectationsTest 2024-03-27 08:44:17 -04:00
Paolo Tranquilli
d9c40488bb Swift: add ThenStmt to control flow 2024-03-27 13:37:24 +01:00
Paolo Tranquilli
b8e38288e3 Swift: add extraction of ThenStmt
These are currently added implicitly by the compiler in the context of
`if`/`switch` expressions. In the future, there might be explicit
`then <expr>` statement useful for cases where one would like to add
more than one statement in the branch, to mark what value to actually
use.

See https://forums.swift.org/t/pitch-multi-statement-if-switch-do-expressions/68443
2024-03-27 13:26:04 +01:00
Arthur Baars
ba89f1b6b1 Merge pull request #15896 from github/aibaars/java-update-output
Java: update expected output
2024-03-27 13:19:52 +01:00
Jami Cogswell
121b24ea7c Java: remove parentheses 2024-03-27 08:16:06 -04:00
Jami Cogswell
35fbc95cc7 Java: remove redundant line 2024-03-27 08:09:40 -04:00
Mathias Vorreiter Pedersen
7bb2b57394 Merge pull request #15964 from rdmarsh2/rdmarsh2/cpp/temp-destructors-extended
C++: IR translation for destruction of temporaries with extended lifetimes
2024-03-27 11:58:48 +00:00
Calum Grant
03bf804a68 Add C++ analysis in separate workflow 2024-03-27 11:44:58 +00:00
Mathias Vorreiter Pedersen
8711232a38 Merge pull request #16069 from jketema/var-templ
C++: Add `VariableTemplateInstantiation` class
2024-03-27 11:31:35 +00:00
Paolo Tranquilli
2382f76317 Swift: ignore experimental ThenStmt 2024-03-27 12:23:37 +01:00
Paolo Tranquilli
f9d10cec08 Swift: fix DeclTranslator.cpp compile errors 2024-03-27 12:21:28 +01:00
Ian Lynagh
6cd94cf253 Merge pull request #16059 from igfoo/igfoo/exprs
Kotlin 2: Accept more location changes
2024-03-27 11:17:07 +00:00
Jeroen Ketema
050682c477 C++: Update expected test results 2024-03-27 12:03:37 +01:00
Paolo Tranquilli
8e9b4336da Merge branch 'main' into alexdenisov/swift-5.10 2024-03-27 11:35:14 +01:00
Jeroen Ketema
27c6e2421c C++: Add VariableTemplateInstantiation class
This adds some uniformity, as we already had `FunctionTemplateInstantiation` and
`ClassTemplateInstantiation` classes.
2024-03-27 11:35:13 +01:00
Tony Torralba
b617667b0e Merge pull request #16062 from atorralba/atorralba/java/more-neutrals
Java: Add more neutrals and improve `java.net.URL` models
2024-03-27 10:41:38 +01:00
Geoffrey White
30c9ec1926 C++: Adjust following discussion. 2024-03-27 09:23:48 +00:00
Tony Torralba
7a0446740b Update java/ql/lib/ext/java.net.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-03-27 09:09:48 +01:00
Arthur Baars
497325455a Java: update expected output 2024-03-26 18:40:22 +01:00
Geoffrey White
b4a6f75ad7 C++: Divide CODEOWNERS responsibilities. 2024-03-26 17:35:07 +00:00
Mathias Vorreiter Pedersen
3e9602854a Merge pull request #16063 from MathiasVP/taint-inheriting-content-for-cpp
C++: Add `TaintInheritingContent`
2024-03-26 17:28:52 +00:00
Mathias Vorreiter Pedersen
3bfaab9182 C++: Remove debugging conjunct. 2024-03-26 17:01:06 +00:00
Mathias Vorreiter Pedersen
6a8c592900 Update cpp/ql/lib/semmle/code/cpp/ir/dataflow/FlowSteps.qll
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2024-03-26 16:59:18 +00:00
Mathias Vorreiter Pedersen
d610d721a4 C++: Add file QLDoc. 2024-03-26 16:47:39 +00:00
Mathias Vorreiter Pedersen
e3744c435a C++: Add change note. 2024-03-26 16:44:16 +00:00
Mathias Vorreiter Pedersen
ec3d041c8d C++: Accept test changes. 2024-03-26 16:40:18 +00:00
Mathias Vorreiter Pedersen
bd2ecd3346 C++: Add test. 2024-03-26 16:38:28 +00:00
Mathias Vorreiter Pedersen
2075716df7 C++: Add 'TaintInheritingContent'. 2024-03-26 16:37:22 +00:00
Tony Torralba
d786ea90a4 Java: Add more neutrals
Adds more neutral models to help the model generator ignore certain callables.

Also improves the precision of certain URL models by using synthetic fields so that the parts of a URL are tainted separately.
2024-03-26 17:31:11 +01:00
Henry Mercer
2de62dfcdd Merge pull request #16058 from github/henrymercer/merge-back-rc-3.13
Merge `rc/3.13` back to `main`
2024-03-26 14:57:31 +00:00
Ian Lynagh
c5604c97bd Kotlin 2: Accept more location changes 2024-03-26 14:10:28 +00:00
Henry Mercer
0646744928 Merge branch 'main' into henrymercer/merge-back-rc-3.13 2024-03-26 12:59:12 +00:00
Michael B. Gale
cf9e2dcea1 Merge pull request #16056 from github/mbg/go/changenote-for-dependency-improvement
Go: Add changenote for `CODEQL_EXTRACTOR_GO_FAST_PACKAGE_INFO` change
2024-03-26 12:50:19 +00:00
Henry Mercer
f89109df7c Merge pull request #16048 from github/post-release-prep/codeql-cli-2.16.6
Post-release preparation for codeql-cli-2.16.6
2024-03-26 12:23:11 +00:00
Max Schaefer
d7258f76d3 Go: Improve QHelp for go/unvalidated-url-redirection.
The example showed a different (and better) fix from what the help claimed, but the suggestion also had a subtle bug that I fixed at the same time.
2024-03-26 10:57:36 +00:00
Michael B. Gale
f84609dbc4 Go: Add changenote for CODEQL_EXTRACTOR_GO_FAST_PACKAGE_INFO change 2024-03-26 10:51:57 +00:00
Tamás Vajk
0c5ea975a4 Merge pull request #16021 from tamasvajk/feature/add-buildless-telemetry
C#: Add high level diagnostic messages for buildless extraction (star…
2024-03-26 11:03:20 +01:00
Dave Bartolomeo
a950de36a0 Merge pull request #16050 from github/dbartol/more-test-fixes
Remove unused data extension in test
2024-03-25 20:50:09 -04:00
Dave Bartolomeo
c11b8f9d51 Remove unused data extension in test 2024-03-25 19:14:54 -04:00
Max Schaefer
ff23f572d0 Merge pull request #16038 from github/max-schaefer/string-break-qhelp
Go: Improve QHelp for `go/unsafe-quoting`.
2024-03-25 20:10:02 +00:00
Max Schaefer
5bc710b406 Apply suggestions from code review
Co-authored-by: Felicity Chapman <felicitymay@github.com>
2024-03-25 19:48:56 +00:00
Dave Bartolomeo
98bf5269a0 Merge pull request #16040 from github/dbartol/qltest-model
Use correct model pack name in qltest data extension
2024-03-25 15:29:16 -04:00
Chris Smowton
f5ebd3d501 Merge pull request #16047 from github/smowton/admin/update-java-supported-version
Update Java version supported to 22
2024-03-25 18:42:35 +00:00
github-actions[bot]
f67b5f9158 Post-release preparation for codeql-cli-2.16.6 2024-03-25 18:17:15 +00:00
Chris Smowton
757b9bb5fa Update Java version supported to 22 2024-03-25 18:01:30 +00:00
Chris Smowton
6fc99e3ad6 Merge pull request #16023 from smowton/smowton/feature/jdk22-support
Java: support Java 22 language features
2024-03-25 17:58:50 +00:00
Henry Mercer
3d82318839 Merge pull request #16045 from github/release-prep/2.16.6
Release preparation for version 2.16.6
2024-03-25 16:59:13 +00:00
github-actions[bot]
71ab804274 Release preparation for version 2.16.6 2024-03-25 16:58:08 +00:00
Chris Smowton
dcebcc35b6 Rename getPatternAtIndex 2024-03-25 16:36:38 +00:00
Chris Smowton
568bddc4a9 Add test cases for cases falling directly out of switch blocks 2024-03-25 16:31:40 +00:00
Chris Smowton
17193ac11b Distinguish record patterns that do or don't declare identifiers 2024-03-25 16:31:40 +00:00
Chris Smowton
a4401963f5 Use getAPattern 2024-03-25 16:31:39 +00:00
Chris Smowton
f347784ec2 autoformat 2024-03-25 16:31:39 +00:00
Chris Smowton
3d9bc6fc89 Note pattern-cases may be missing some type-accesses 2024-03-25 16:31:39 +00:00
Chris Smowton
5e0961b348 Account for new possible child index gap 2024-03-25 16:31:39 +00:00
Chris Smowton
9fa2f19990 Add test for guards in the presence of fall-through between pattern and constant cases 2024-03-25 16:31:39 +00:00
Chris Smowton
c48e64e536 Add tests for the combination of anonymous labels and a guard 2024-03-25 16:31:39 +00:00
Chris Smowton
1e0766dffa Add tests for case statement type test dominance against anonymous labels and fall-through 2024-03-25 16:31:39 +00:00
Chris Smowton
f2ff6c476a Add printast tests for anonymous variables 2024-03-25 16:31:38 +00:00
Chris Smowton
5cb5ee026c Fix pretty-printing of anonymous vars and multiple patterns; add test 2024-03-25 16:31:38 +00:00
Chris Smowton
f317f782ae Add test for control-flow with mixed patterns, constants and fall-through 2024-03-25 16:31:38 +00:00
Chris Smowton
6cf956d07a Add CFG test for anonymous variables and fall-throughs with pattern cases 2024-03-25 16:31:38 +00:00
Chris Smowton
cc8dcf63b0 Convert test to use an anonymous local 2024-03-25 16:31:38 +00:00
Chris Smowton
ee36e3b72b autoformat 2024-03-25 16:31:38 +00:00
Chris Smowton
403e86878c Don't mistake a rule case for a fall-through edge 2024-03-25 16:31:37 +00:00
Chris Smowton
5243a62a41 Accept test changes 2024-03-25 16:31:37 +00:00
Chris Smowton
c0874ab04b Fix pattern-case variable pretty-printer 2024-03-25 16:31:37 +00:00
Chris Smowton
f66811048d Fix next-normal-statement predicate 2024-03-25 16:31:37 +00:00
Chris Smowton
bc0724e2b3 Add change note 2024-03-25 16:31:37 +00:00
Chris Smowton
d5443b3f10 Remove dead code 2024-03-25 16:31:37 +00:00
Chris Smowton
29e93edf90 Dataflow: restrict pattern-case flow to unique patterns. 2024-03-25 16:31:37 +00:00
Chris Smowton
00c7dd5f92 Fix a stray use of getPattern 2024-03-25 16:31:36 +00:00
Chris Smowton
e59487a324 Don't regard cases with multiple patterns as conducting a type test 2024-03-25 16:31:36 +00:00
Chris Smowton
c7cb885e71 Add missing javadoc and getUniquePattern predicate 2024-03-25 16:31:36 +00:00
Chris Smowton
f44becea7f Implement multiple pattern case and fall-through pattern case support 2024-03-25 16:31:36 +00:00
Chris Smowton
c283894b4b Fix typo 2024-03-25 16:31:36 +00:00
Chris Smowton
33b807f3bb Parameters and local variables: add isAnonymous predicate 2024-03-25 16:31:36 +00:00
Edward Minnix III
7377cbb46e Merge pull request #15930 from egregius313/egregius313/csharp/mad/database/dapper-sources
C#: Sources for the `Dapper` database library
2024-03-25 11:21:51 -04:00
Rasmus Wriedt Larsen
d516db6abc Merge pull request #15903 from yoff/python/test-MaD-keyword-argument
Python: test MaD syntax for keyword argument
2024-03-25 15:51:49 +01:00
Dave Bartolomeo
d805bbcd27 Use correct model pack name in qltest data extension 2024-03-25 10:31:11 -04:00
Max Schaefer
120fb93c23 Go: Improve QHelp for go/unsafe-quoting. 2024-03-25 13:32:51 +00:00
Paolo Tranquilli
dea922958b Merge pull request #16034 from github/redsun82/swift-move-integration-tests-to-internal
Swift: prepare integration tests for internal running
2024-03-25 14:08:47 +01:00
Paolo Tranquilli
9c9f4b956e Swift: fix db in diagnostics_test_utils.py 2024-03-25 13:53:27 +01:00
Tamas Vajk
2f0b54c801 Refactor buildless telemetry logging 2024-03-25 12:48:27 +01:00
Ian Lynagh
55226c48a6 Merge pull request #16022 from igfoo/igfoo/k2_exprs
Kotlin 2: Accept more location changes
2024-03-25 11:38:15 +00:00
Tamas Vajk
b94d33d78d Add buildless failed diagnostic 2024-03-25 12:27:36 +01:00
Paolo Tranquilli
7f53509022 Merge branch 'main' into redsun82/swift-move-integration-tests-to-internal 2024-03-25 12:22:00 +01:00
Paolo Tranquilli
6707fc3a7c Swift: remove wrong flag in runner.py 2024-03-25 12:20:13 +01:00
Paolo Tranquilli
148033e020 Swift: fix assertion diagnostics test 2024-03-25 12:05:22 +01:00
Tamas Vajk
5ab5244171 Change public messages to not include 'buildless' 2024-03-25 11:59:29 +01:00
Chris Smowton
10afb1cd93 Merge pull request #16030 from smowton/smowton/admin/buildless-wording-update
Java: Update buildless test expectations
2024-03-25 10:57:56 +00:00
Paolo Tranquilli
ca5d85c57e Merge branch 'main' into redsun82/swift-move-integration-tests-to-internal 2024-03-25 11:56:48 +01:00
Paolo Tranquilli
0fa40af131 Swift: fix last references to old integration test location 2024-03-25 11:49:19 +01:00
Max Schaefer
ffbe3e6ed4 Merge pull request #16020 from github/max-schaefer/go-path-injection-qhelp
Go: Update query help for `go/path-injection` to include example fixes.
2024-03-25 10:25:36 +00:00
Owen Mansel-Chan
f2db9ce312 Merge pull request #16028 from owen-mc/java/sensitive-log-whitelist-tokenimage
Java: whitelist variable name `tokenImage` for `java/sensitive-log` as it's used in code generated by JavaCC
2024-03-25 10:02:19 +00:00
Paolo Tranquilli
5a771ad2cf Swift: bump python version 2024-03-25 10:42:16 +01:00
Tamás Vajk
d6374f65e4 Merge pull request #15957 from tamasvajk/feature/limit-message-extraction
C#: Limit extracted compilation and extraction messages
2024-03-25 10:30:10 +01:00
Paolo Tranquilli
762b4ce42e Swift: prepare integration tests for internal running
This harmonizes Swift integration tests with the rest of the repository,
to prepare for the internal integration test runner to run them. The
stripped down runner is kept compatible, so that current CI can still
use it now. Maybe it will be kept for developer use.

This PR includes:
* moving the integration tests inside `ql`
* editing `qlpack.yml` so that the internal runner can use it
* change database directory to be `test-db` rather than `db`
2024-03-25 10:17:55 +01:00
Owen Mansel-Chan
ac6c4add14 Apply suggestions from code review
Co-authored-by: Chris Smowton <smowton@github.com>
2024-03-24 20:20:37 +00:00
Chris Smowton
d8686e02a8 Update test expectations 2024-03-24 17:57:27 +00:00
Owen Mansel-Chan
821f399193 Add change note 2024-03-23 23:51:52 +00:00
Owen Mansel-Chan
f4b3bae88b Add test for ParseException use of tokenImage 2024-03-23 23:48:16 +00:00
Owen Mansel-Chan
4832dc51ed Whitelist variable name tokenImage 2024-03-23 21:33:02 +00:00
Owen Mansel-Chan
63a04c056a Add test with tokenImage as used in JavaCC 2024-03-23 21:30:33 +00:00
Aditya Sharad
1a8932bc28 Merge pull request #16024 from github/changedocs/2.16.5
Update CodeQL CLI to version 2.16.5
2024-03-22 09:32:52 -07:00
Erik Krogh Kristensen
45ce988943 Merge pull request #16002 from erik-krogh/tarBlank
JS: change the precision of the `js/unsafe-external-link` query to `low`
2024-03-22 17:12:58 +01:00
Florin Coada
c653f1ce8c Add CodeQL 2.16.5 changelog 2024-03-22 15:28:54 +00:00
Max Schaefer
034ed17227 Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-03-22 15:24:29 +00:00
Jeroen Ketema
d9b0a5918c Merge pull request #16018 from jketema/tls-precision
C++: Add precision to `cpp/boost/tls-settings-misconfiguration` and `cpp/boost/use-of-deprecated-hardcoded-security-protocol`
2024-03-22 16:17:34 +01:00
Jeroen Ketema
453cdfa513 C++: Add change note 2024-03-22 15:52:52 +01:00
Ian Lynagh
63e34c4dec Kotlin 2: Accept more location changes 2024-03-22 14:09:20 +00:00
Edward Minnix III
1785086ccb Merge pull request #15784 from egregius313/egregius313/csharp/dataflow/sources/file
C#: Add source models for `file` threat model/source kind for .NET standard library
2024-03-22 09:50:30 -04:00
Michael Nebel
a07ee8e961 C#: Update the AsList model to a value flow model. 2024-03-22 14:40:25 +01:00
Tamas Vajk
178a45af25 C#: Add high level diagnostic messages for buildless extraction (start, success) 2024-03-22 14:27:36 +01:00
Max Schaefer
bc9396e0e6 Address suggestions from review. 2024-03-22 13:19:36 +00:00
Michael B. Gale
f48e295f4a Merge pull request #16019 from p-/p--weak-enc-ecb-qhelp
C#: add hint regarding ECB to weak encryption QHelp
2024-03-22 13:09:08 +00:00
Michael Nebel
ca72b0583d C#: Update source and sink expected test output. 2024-03-22 13:59:47 +01:00
Erik Krogh Kristensen
7d968184fd improve the change-note
Co-authored-by: Asger F <asgerf@github.com>
2024-03-22 13:58:34 +01:00
Ed Minnix
4b13ad1310 Fix flow summary tests 2024-03-22 13:46:20 +01:00
Ed Minnix
9ed8ca27a1 Fix test and model 2024-03-22 13:46:19 +01:00
Ed Minnix
1f04229def Fix typo 2024-03-22 13:46:19 +01:00
Ed Minnix
73b4e8fe6a Add WithElement identifier to AsList method 2024-03-22 13:46:19 +01:00
Ed Minnix
9b23bfa038 Execute methods which return objects
The `Execute` method returns `int` for "number of rows affected". But
some of the other `Execute*` methods return objects.
2024-03-22 13:46:19 +01:00
Ed Minnix
5885938eaf Use wildcard signatures for Query methods 2024-03-22 13:46:19 +01:00
Ed Minnix
8223781978 Fix FlowSummaries tests 2024-03-22 13:46:19 +01:00
Ed Minnix
5ca6b40c34 Change note 2024-03-22 13:46:18 +01:00
Ed Minnix
23aeb1d878 Add tests 2024-03-22 13:46:18 +01:00
Ed Minnix
98285b5171 Add AsList summary 2024-03-22 13:46:18 +01:00
Ed Minnix
87ad170067 Dapper source models 2024-03-22 13:46:18 +01:00
Ian Lynagh
01475fd8ba Merge pull request #16011 from igfoo/igfoo/legacy_vars
Java/Kotlin: Remove references to legacy ODASA_SNAPSHOT env var
2024-03-22 12:38:37 +00:00
Max Schaefer
4e4cd52f63 Go: Update query help for go/path-injection to include example fixes. 2024-03-22 11:45:59 +00:00
Peter Stöckli
d62d68a40b C#: add hint regarding ECB to weak encryption QHelp 2024-03-22 12:08:30 +01:00
Rasmus Wriedt Larsen
69f6e1e263 Merge pull request #16010 from RasmusWL/perf
Python: Two small join-order fixes
2024-03-22 11:36:17 +01:00
Jeroen Ketema
adfb3c3d50 C++: Simplify cpp/boost/tls-settings-misconfiguration 2024-03-22 11:22:11 +01:00
yoff
c520cb6d58 Merge branch 'main' into python/test-MaD-keyword-argument 2024-03-22 10:56:08 +01:00
Rasmus Lerchedahl Petersen
eef60c9ad2 python: add test for "ReturnValue.TupleElement[0,1]"
also synchronise files
2024-03-22 10:54:12 +01:00
Jeroen Ketema
fb4ed39d89 Merge pull request #16017 from jketema/destructors21
C++: Add destructor test cases for AV Rule 114
2024-03-22 10:50:27 +01:00
Jeroen Ketema
a770bddff0 C++: Add precision to cpp/boost/tls-settings-misconfiguration and cpp/boost/use-of-deprecated-hardcoded-security-protocol
Also clean up the names of the queries while here.
2024-03-22 10:48:18 +01:00
Jeroen Ketema
3f0ce98ccb C++: Add destructor test cases for AV Rule 114 2024-03-22 10:25:47 +01:00
Tamas Vajk
205d6a3bc5 Extract total number of diagnostic per ID and compilation 2024-03-22 08:55:41 +01:00
Tamas Vajk
fa7f437e71 Code quality improvement 2024-03-22 08:16:11 +01:00
Jeroen Ketema
eca6c00003 Merge pull request #16014 from jketema/destructors20
C++: Handle destructors of range-based for-loop, if, and switch initializer statements
2024-03-21 21:04:23 +01:00
Ed Minnix
c7a746e3dc Flow summary tests 2024-03-21 13:15:45 -04:00
Ed Minnix
3e3eceea5f Typo 2024-03-21 13:06:34 -04:00
Ed Minnix
e2c2d574f8 Add FileInfo::OpenText 2024-03-21 13:06:33 -04:00
Ed Minnix
46a9bb9804 Change note 2024-03-21 13:06:31 -04:00
Ed Minnix
08611f0c9c Fix flow summary tests 2024-03-21 13:06:30 -04:00
Ed Minnix
e14e47cd73 Fix Stream::Read(Span<byte>) model 2024-03-21 13:06:28 -04:00
Ed Minnix
d6f085373e System.IO.Stream::ReadExactly models 2024-03-21 13:06:27 -04:00
Ed Minnix
2a73677fd2 Missing Stream::ReadAsync overload 2024-03-21 13:06:26 -04:00
Ed Minnix
a698684fec System.IO.Stream::ReadAtLeast 2024-03-21 13:06:24 -04:00
Ed Minnix
3e29a8d2a1 System.IO files test 2024-03-21 13:06:23 -04:00
Ed Minnix
d387e6d068 Fix flow-summary tests 2024-03-21 13:06:21 -04:00
Ed Minnix
9232fafde1 Add System.IO.Stream::Read(Span<Byte>) model 2024-03-21 13:06:20 -04:00
Ed Minnix
a8c5e4e0f2 FileInfo source models 2024-03-21 13:06:18 -04:00
Ed Minnix
bb9b0eabf2 Add BufferedStream summary models 2024-03-21 13:06:17 -04:00
Ed Minnix
a5b801b31f Add File reading methods 2024-03-21 13:06:15 -04:00
Arthur Baars
c219b1a3c7 Merge pull request #16013 from github/rc/3.13
Merge rc/3.13 into main
2024-03-21 16:04:58 +01:00
Rasmus Wriedt Larsen
93f940aa9c Python: Join-order improvement for DataFlowDispatch::TrackAttrReadInput
I was surprised to see that this predicate actually gets evaluated 3 times

- Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@c15596yu was evaluated in 74 iterations totaling 165ms (delta sizes total: 113119).
- Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@3459ejws was evaluated in 30 iterations totaling 76ms (delta sizes total: 32555).
- Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@5ac22jwq was evaluated in 30 iterations totaling 108ms (delta sizes total: 32555).

It does however fit with it being used in exactly 3 places: https://github.com/search?q=repo%3Agithub%2Fcodeql+%2FattrReadTracker%5C%28%2F&type=code -- so I assume it's because each use forces a new evaluation. Although that's something we could look into solving, for now I'm just trying to fix the join-order.

Initial

```
Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@3459ejws was evaluated in 30 iterations totaling 76ms (delta sizes total: 32555).
        7068090   ~0%    {2} r1 = SCAN Attributes::AttrRead#class#f6c3f431 OUTPUT In.0, In.0
                         {2}    | AND NOT `DataFlowDispatch::TrackAttrReadInput::start/2#67f26627#prev`(FIRST 2)
        3901178   ~5%    {2}    | SCAN OUTPUT In.1, In.1
        3901178   ~0%    {3}    | JOIN WITH `Attributes::AttrRef.getObject/0#dispred#d7cd0a97` ON FIRST 1 OUTPUT Rhs.1, Lhs.0, Lhs.1

          13615   ~1%    {2} r2 = JOIN r1 WITH `DataFlowDispatch::classTracker/1#d11f2237#reorder_1_0#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

             94   ~2%    {2} r3 = JOIN r1 WITH `DataFlowDispatch::superCallTwoArgumentTracker/2#d18be99f#reorder_2_0_1#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

          18846   ~1%    {2} r4 = JOIN r1 WITH `DataFlowDispatch::classInstanceTracker/1#d73ecef4#prev_delta_1#join_rhs` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

          32555   ~1%    {2} r5 = r2 UNION r3 UNION r4
                         return r5
```

==>

```
Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@f2517jwq was evaluated in 30 iterations totaling 12ms (delta sizes total: 32704).
        186719  ~121%    {1} r1 = SCAN `DataFlowDispatch::classInstanceTracker/1#d73ecef4#prev_delta` OUTPUT In.1

        164342  ~158%    {1} r2 = SCAN `DataFlowDispatch::classTracker/1#d11f2237#reorder_1_0#prev_delta` OUTPUT In.0

            96    ~0%    {1} r3 = SCAN `DataFlowDispatch::superCallTwoArgumentTracker/2#d18be99f#reorder_2_0_1#prev_delta` OUTPUT In.0

        351157   ~80%    {1} r4 = r1 UNION r2 UNION r3
         88074   ~14%    {1}    | JOIN WITH `Attributes::AttrRef.getObject/0#dispred#d7cd0a97_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1
         41789   ~18%    {2}    | JOIN WITH Attributes::AttrRead#class#f6c3f431 ON FIRST 1 OUTPUT Lhs.0, Lhs.0
                         {2}    | AND NOT `DataFlowDispatch::TrackAttrReadInput::start/2#67f26627#prev`(FIRST 2)
         32883    ~2%    {2}    | SCAN OUTPUT In.1, In.1
                         return r4
```

AND

initial

```
Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@c15596yu was evaluated in 74 iterations totaling 165ms (delta sizes total: 113119).
        17434622   ~0%    {2} r1 = SCAN Attributes::AttrRead#class#f6c3f431 OUTPUT In.0, In.0
                          {2}    | AND NOT `DataFlowDispatch::TrackAttrReadInput::start/2#67f26627#prev`(FIRST 2)
         9483976   ~4%    {2}    | SCAN OUTPUT In.1, In.1
         9483976   ~0%    {3}    | JOIN WITH `Attributes::AttrRef.getObject/0#dispred#d7cd0a97` ON FIRST 1 OUTPUT Rhs.1, Lhs.0, Lhs.1

           19258   ~1%    {2} r2 = JOIN r1 WITH `DataFlowDispatch::classInstanceTracker/1#d73ecef4#reorder_1_0#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

            1654   ~1%    {2} r3 = JOIN r1 WITH `DataFlowDispatch::superCallNoArgumentTracker/1#0a2e8a06#reorder_1_0#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

            1314   ~4%    {2} r4 = JOIN r1 WITH `DataFlowDispatch::clsArgumentTracker/1#47339327#reorder_1_0#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

              94   ~2%    {2} r5 = JOIN r1 WITH `DataFlowDispatch::superCallTwoArgumentTracker/2#d18be99f#reorder_2_0_1#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

           77217   ~0%    {2} r6 = JOIN r1 WITH `DataFlowDispatch::selfTracker/1#f157aa27#reorder_1_0#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

           13632   ~1%    {2} r7 = JOIN r1 WITH `DataFlowDispatch::classTracker/1#d11f2237#reorder_1_0#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

          113169   ~0%    {2} r8 = r2 UNION r3 UNION r4 UNION r5 UNION r6 UNION r7
                          return r8
```
==>

```
Pipeline standard for DataFlowDispatch::TrackAttrReadInput::start/2#67f26627@d732e6yt was evaluated in 74 iterations totaling 31ms (delta sizes total: 113129).
        186719  ~150%    {1} r1 = SCAN `DataFlowDispatch::classInstanceTracker/1#d73ecef4#reorder_1_0#prev_delta` OUTPUT In.0

          1669    ~0%    {1} r2 = SCAN `DataFlowDispatch::superCallNoArgumentTracker/1#0a2e8a06#reorder_1_0#prev_delta` OUTPUT In.0

          3425   ~15%    {1} r3 = SCAN `DataFlowDispatch::clsArgumentTracker/1#47339327#prev_delta` OUTPUT In.1

            96    ~0%    {1} r4 = SCAN `DataFlowDispatch::superCallTwoArgumentTracker/2#d18be99f#reorder_2_0_1#prev_delta` OUTPUT In.0

        123310    ~0%    {1} r5 = SCAN `DataFlowDispatch::selfTracker/1#f157aa27#reorder_1_0#prev_delta` OUTPUT In.0

        164342  ~581%    {1} r6 = SCAN `DataFlowDispatch::classTracker/1#d11f2237#reorder_1_0#prev_delta` OUTPUT In.0

        479561   ~94%    {1} r7 = r1 UNION r2 UNION r3 UNION r4 UNION r5 UNION r6
        169424    ~2%    {1}    | JOIN WITH `Attributes::AttrRef.getObject/0#dispred#d7cd0a97_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1
        116290    ~0%    {2}    | JOIN WITH Attributes::AttrRead#class#f6c3f431 ON FIRST 1 OUTPUT Lhs.0, Lhs.0
                         {2}    | AND NOT `DataFlowDispatch::TrackAttrReadInput::start/2#67f26627#prev`(FIRST 2)
        113160    ~0%    {2}    | SCAN OUTPUT In.1, In.1
                         return r7
```
2024-03-21 15:55:58 +01:00
Jeroen Ketema
98de4e209b C++: Handle destructors of if and switch initializer statements 2024-03-21 15:47:11 +01:00
Jeroen Ketema
9cc287dff1 C++: Handle destructors of range-based for-loop initializer statements 2024-03-21 15:47:11 +01:00
Cornelius Riemenschneider
be245dd4b2 Merge pull request #16012 from github/criemen/swift-linux-sandbox
Swift genrule: Replace local with no-sandbox.
2024-03-21 15:06:47 +01:00
Rasmus Wriedt Larsen
bfa8515b28 Python: Apply suggestions from code review
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2024-03-21 14:51:45 +01:00
Cornelius Riemenschneider
79094e4b89 Swift genrule: Replace local with no-sandbox.
This allows the bazel cache to cache this genrule invocation.
It shouldn't depend on system-specific binaries, so
I believe this is correct.
This is the only part of our build where we otherwise
need to recompute parts after pulling in a full cache.
2024-03-21 13:51:22 +00:00
Ian Lynagh
1b3605754f Java: Add a changenote for dropping ODASA_SNAPSHOT support 2024-03-21 13:38:54 +00:00
Tamás Vajk
0aa7de295b Merge pull request #16004 from tamasvajk/feature/adjust-incorrect-compare-to
C#: Simplify the output of `cs/wrong-compareto-signature` to remove e…
2024-03-21 14:38:54 +01:00
Ian Lynagh
33fe5abf94 Kotlin: Remove references to legacy ODASA_SNAPSHOT env var 2024-03-21 13:29:40 +00:00
Henry Mercer
4e3a6e2140 Merge pull request #15874 from github/henrymercer/mark-loc-as-telemetry
Show lines of code data in debug mode only
2024-03-21 12:20:09 +00:00
Rasmus Wriedt Larsen
cff63ad5d5 Python: Fix small join-order problem for call-graph
problem is:
```
           14294  ~33%    {1} r23 = r21 UNION r22
           13626   ~0%    {2}    | JOIN WITH `DataFlowPublic::Node.getEnclosingCallable/0#dispred#be95825a` ON FIRST 1 OUTPUT Rhs.1, Lhs.0
        11871493   ~2%    {2}    | JOIN WITH `DataFlowPublic::Node.getEnclosingCallable/0#dispred#be95825a_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
         6810938   ~3%    {2}    | JOIN WITH num#DataFlowPublic::TCfgNode#2cd2fb22_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1
               0   ~0%    {4}    | JOIN WITH `DataFlowDispatch::resolveMethodCall/4#3067f1f1#reorder_0_3_1_2#prev` ON FIRST 2 OUTPUT Rhs.3, Lhs.1, Lhs.0, Rhs.2
               0   ~0%    {4}    | JOIN WITH num#DataFlowDispatch::CallTypeClassMethod#3508c3e5 ON FIRST 1 OUTPUT Lhs.3, Lhs.2, Lhs.0, Lhs.1
               0   ~0%    {4}    | JOIN WITH `DataFlowDispatch::resolveCall/3#454c02d8#reorder_1_0_2#prev` ON FIRST 3 OUTPUT Lhs.3, Lhs.1, Lhs.0, Lhs.2
               0   ~0%    {5}    | JOIN WITH num#DataFlowDispatch::TSelfArgumentPosition#de6d64b8 CARTESIAN PRODUCT OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.0, Rhs.0
```
that is, it does cartesian product of DataFlowPublic::Node.getEnclosingCallable

After fix

```
        14294  ~33%    {1} r23 = r21 UNION r22
            0   ~0%    {4}    | JOIN WITH `DataFlowDispatch::resolveMethodCall/4#3067f1f1#reorder_3_0_1_2#prev` ON FIRST 1 OUTPUT Rhs.3, Lhs.0, Rhs.1, Rhs.2
            0   ~0%    {4}    | JOIN WITH num#DataFlowDispatch::CallTypeClassMethod#3508c3e5 ON FIRST 1 OUTPUT Lhs.3, Lhs.2, Lhs.0, Lhs.1
            0   ~0%    {4}    | JOIN WITH `DataFlowDispatch::resolveCall/3#454c02d8#reorder_1_0_2#prev` ON FIRST 3 OUTPUT Lhs.1, Lhs.3, Lhs.0, Lhs.2
            0   ~0%    {5}    | JOIN WITH num#DataFlowPublic::TCfgNode#2cd2fb22 ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0, Lhs.2, Lhs.3
            0   ~0%    {5}    | JOIN WITH `DataFlowPublic::Node.getEnclosingCallable/0#dispred#be95825a` ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.2, Lhs.3, Lhs.4
            0   ~0%    {4}    | JOIN WITH `DataFlowPublic::Node.getEnclosingCallable/0#dispred#be95825a` ON FIRST 2 OUTPUT Lhs.0, Lhs.2, Lhs.3, Lhs.4
            0   ~0%    {5}    | JOIN WITH num#DataFlowDispatch::TSelfArgumentPosition#de6d64b8 CARTESIAN PRODUCT OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.0, Rhs.0
```

Overall stats

(old)
Pipeline standard for DataFlowDispatch::getCallArg/5#21589076@b30c7vxg was evaluated in 51 iterations totaling 54ms (delta sizes total: 38247).

==>

(new)
Pipeline standard for DataFlowDispatch::getCallArg/5#21589076@c1559vxu was evaluated in 51 iterations totaling 28ms (delta sizes total: 38247).
2024-03-21 12:31:58 +01:00
Jeroen Ketema
ccc5a80d93 Merge pull request #16008 from jketema/destructors19
C++: Handle `getInitializingExpr` in PrintAST
2024-03-21 12:22:48 +01:00
Rasmus Wriedt Larsen
2aa5ae41fb Python: Fix join-order problem in SqlAlchemy
No major performance impact, more of a learning example for myself (had +3000 join order badness).

Initial tuple counts

```
Evaluated recursive predicate SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0@594cfx2g in 1ms on iteration 1 (delta size: 4).
Evaluated relational algebra for predicate SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0@594cfx2g on iteration 1 running pipeline base with tuple counts:
        37793   ~0%    {3} r1 = JOIN `ApiGraphs::API::Node.getACall/0#dispred#312deb92_10#join_rhs` WITH DataFlowPublic::CallCfgNode#b8ddbf81 ON FIRST 1 OUTPUT Lhs.1, Lhs.0, Rhs.1
            0   ~0%    {2}    | JOIN WITH `SqlAlchemy::SqlAlchemy::Connection::classRef/0#565fc3ad` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

           30   ~0%    {5} r2 = JOIN DataFlowPublic::CallCfgNode#b8ddbf81 WITH `DataFlowPublic::MethodCallNode.calls/2#dispred#1dd1e0f4#ffb` ON FIRST 1 OUTPUT Lhs.0, Lhs.1, Rhs.1, Rhs.2, _
                       {4}    | REWRITE WITH NOT [NOT [Tmp.4 := "begin", TEST InOut.3 = Tmp.4], NOT [Tmp.4 := "connect", TEST InOut.3 = Tmp.4]] KEEPING 4
           21   ~0%    {3}    | SCAN OUTPUT In.2, In.0, In.1
            4   ~0%    {2}    | JOIN WITH `SqlAlchemy::SqlAlchemy::Engine::instance/0#1828baef` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

            4   ~0%    {2} r3 = r1 UNION r2
                       return r3
```

which is fixed by the only_bind_out

```
Evaluated recursive predicate SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0@49effxtg in 0ms on iteration 1 (delta size: 0).
Evaluated relational algebra for predicate SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0@49effxtg on iteration 1 running pipeline base with tuple counts:
        0  ~0%    {1} r1 = JOIN `SqlAlchemy::SqlAlchemy::Connection::classRef/0#565fc3ad` WITH `ApiGraphs::API::Node.getACall/0#dispred#312deb92` ON FIRST 1 OUTPUT Rhs.1
        0  ~0%    {2}    | JOIN WITH DataFlowPublic::CallCfgNode#b8ddbf81 ON FIRST 1 OUTPUT Lhs.0, Rhs.1
                  return r1
```

We also had this initial problem

```
Evaluated recursive predicate SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0@594cfx2g in 1ms on iteration 4 (delta size: 0).
Evaluated relational algebra for predicate SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0@594cfx2g on iteration 4 running pipeline standard with tuple counts:
        48722   ~6%    {2} r1 = DataFlowPublic::CallCfgNode#b8ddbf81 AND NOT SqlAlchemy::SqlAlchemy::Connection::ConnectionConstruction#45e716e0#prev(FIRST 2)

        48722   ~3%    {3} r2 = SCAN r1 OUTPUT In.0, _, In.1
        48722   ~1%    {3}    | REWRITE WITH Out.1 := "connect"
           16   ~0%    {3}    | JOIN WITH `DataFlowPublic::MethodCallNode.calls/2#dispred#1dd1e0f4#ffb_021#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.0, Lhs.2
            0   ~0%    {2}    | JOIN WITH `SqlAlchemy::SqlAlchemy::Connection::instance/0#5ed87c17#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

        48722   ~3%    {3} r3 = SCAN r1 OUTPUT In.0, _, In.1
        48722   ~2%    {3}    | REWRITE WITH Out.1 := "execution_options"
            9   ~0%    {3}    | JOIN WITH `DataFlowPublic::MethodCallNode.calls/2#dispred#1dd1e0f4#ffb_021#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.0, Lhs.2
            0   ~0%    {2}    | JOIN WITH `SqlAlchemy::SqlAlchemy::Connection::instance/0#5ed87c17#prev_delta` ON FIRST 1 OUTPUT Lhs.1, Lhs.2

            0   ~0%    {2} r4 = r2 UNION r3
                       return r4
```

which is fixed by `connectionConstruction_helper`

```
Evaluated recursive predicate SqlAlchemy::SqlAlchemy::Connection::helper/0#62cfc178#b@4f295yef in 1ms on iteration 4 (delta size: 0).
Evaluated relational algebra for predicate SqlAlchemy::SqlAlchemy::Connection::helper/0#62cfc178#b@4f295yef on iteration 4 running pipeline standard with tuple counts:
         4  ~0%    {1} r1 = JOIN `SqlAlchemy::SqlAlchemy::Connection::instance/1#029b4c87#prev_delta` WITH `TypeTrackingImpl::TypeTracker::end/0#2ac2cfd4` ON FIRST 1 OUTPUT Lhs.1
        16  ~0%    {1}    | JOIN WITH `LocalSources::Cached::hasLocalSource/2#8b3ee0ec_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1
         0  ~0%    {3}    | JOIN WITH `DataFlowPublic::MethodCallNode.calls/2#dispred#1dd1e0f4#ffb_102#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Rhs.2, _
         0  ~0%    {2}    | REWRITE WITH NOT [NOT [Tmp.2 := "connect", TEST InOut.1 = Tmp.2], NOT [Tmp.2 := "execution_options", TEST InOut.1 = Tmp.2]] KEEPING 2
         0  ~0%    {1}    | JOIN WITH DataFlowPublic::CallCfgNode#b8ddbf81 ON FIRST 1 OUTPUT Lhs.0
         0  ~0%    {1}    | AND NOT `SqlAlchemy::SqlAlchemy::Connection::helper/0#62cfc178#b#prev`(FIRST 1)
                   return r1
```
2024-03-21 11:55:49 +01:00
Jeroen Ketema
4c4ebd907e C++: Update more expected test results 2024-03-21 11:54:29 +01:00
Jeroen Ketema
a3ae304dfe C++: Handle getInitializingExpr in PrintAST 2024-03-21 11:32:23 +01:00
Jeroen Ketema
33c524d9fd Merge pull request #16003 from jketema/destructors18
C++: Add tests showing missing destructors for initialization statements
2024-03-21 11:28:54 +01:00
Tamas Vajk
9d655520cc Code quality improvement 2024-03-21 11:26:45 +01:00
Mathias Vorreiter Pedersen
dc5ee7c8b4 Merge pull request #16007 from MathiasVP/fix-tls-settings-misconfiguration
C++: Fix `cpp/boost/tls-settings-misconfiguration` FPs
2024-03-21 10:16:37 +00:00
Mathias Vorreiter Pedersen
7fb64268bd Merge pull request #15997 from MathiasVP/simplify-guard-in-missing-check-scanf
C++: Simplify use of guard conditions in `cpp/missing-check-scanf`
2024-03-21 10:16:12 +00:00
Tamas Vajk
d0c09f43a9 Add change note 2024-03-21 11:13:42 +01:00
Paolo Tranquilli
eb7f07dc3f Merge pull request #15967 from github/redsun82/test
Swift: add `-headerpad_max_install_names` to link options
2024-03-21 11:11:53 +01:00
Tom Hvitved
c0f80ecd2f Merge pull request #15994 from hvitved/csharp/no-trap-stack-in-buildless
C#: Avoid using TRAP stack in buildless mode
2024-03-21 10:46:08 +01:00
erik-krogh
54a1c25276 change the precision of the js/unsafe-external-link query to low 2024-03-21 10:32:15 +01:00
Tamas Vajk
9da8cb1165 C#: Simplify the output of cs/wrong-compareto-signature to remove entity locations 2024-03-21 10:27:55 +01:00
Jeroen Ketema
06313b9bb6 Merge pull request #15998 from MathiasVP/simplify-guard-in-incorrectly-check-scanf
C++: Simplify use of guard conditions in `cpp/incorrectly-checked-scanf`
2024-03-21 10:10:03 +01:00
Jeroen Ketema
84646cd795 C++: Add tests showing missing destructors for initialization statements
Incidentially this also shows that for contructs like `if (char x = ...)`, so
there is an initialization but not initializer statement, the initialization
is not displayed in the AST, although the IR does contain the initialization.
2024-03-21 09:40:00 +01:00
Michael Nebel
6619be3137 Merge pull request #15940 from michaelnebel/csharp/sourcesinktests
C#: Source- and sink tests.
2024-03-21 08:12:16 +01:00
Jeroen Ketema
ec071cde51 Merge pull request #15991 from jketema/destructors17
C++: Handle destruction of temporaries in expressions with a `thow` at the root
2024-03-21 07:47:09 +01:00
Jeroen Ketema
9300b04def C++: Update test results 2024-03-21 00:05:30 +01:00
Henry Mercer
a76832f4e0 Mark LOC queries as debug instead 2024-03-20 21:18:55 +00:00
Tom Hvitved
8f56edea80 Merge pull request #15966 from hvitved/treesitter-split-up-node-info-table
Tree-sitter: Split up `ast_node_info` table into two tables
2024-03-20 20:38:18 +01:00
Mathias Vorreiter Pedersen
0ef8c7d87f C++: Accept test changes. 2024-03-20 18:05:14 +00:00
Mathias Vorreiter Pedersen
1330c885c8 C++: Use 'asIndirectExpr' in the sink of 'ExistsAnyFlowConfig. 2024-03-20 18:04:59 +00:00
Mathias Vorreiter Pedersen
f31bb1391d C++: Simplify 'checkedForEof'. 2024-03-20 16:59:39 +00:00
Mathias Vorreiter Pedersen
5476f42d2c C++: Simplify use of 'GuardCondition's in 'cpp/missing-check-scanf'. 2024-03-20 16:44:43 +00:00
Mathias Vorreiter Pedersen
e3be2057d3 Merge pull request #15996 from MathiasVP/missing-check-scanf-path-problem
Make `cpp/missing-check-scanf` a `path-problem` query
2024-03-20 16:42:47 +00:00
Mathias Vorreiter Pedersen
96cd259eda C++: Add change note. 2024-03-20 14:56:39 +00:00
Mathias Vorreiter Pedersen
14aff5c94c C++: Convert 'cpp/missing-check-scanf' to a path-problem query. 2024-03-20 14:54:53 +00:00
Mathias Vorreiter Pedersen
0fe3072a65 Merge pull request #15988 from MathiasVP/clean-up-missing-check-scanf
C++: Rewrite 'cpp/missing-check-scanf' to use standard dataflow configs
2024-03-20 14:50:08 +00:00
Michael Nebel
969676975d C#: Address review comments. 2024-03-20 15:28:56 +01:00
Michael B. Gale
616015fddf Merge pull request #15935 from github/mbg/go/speed-up-dependencies 2024-03-20 14:26:46 +00:00
Tom Hvitved
79dc7fcc04 C#: Avoid using TRAP stack in buildless mode 2024-03-20 15:21:36 +01:00
Taus
1d38ca371b Merge pull request #15845 from github/tausbn/python-extractor-fix-build
Python: Build external extractor
2024-03-20 15:18:59 +01:00
Michael B. Gale
648543f2fb Merge pull request #15989 from github/mbg/docs/go-1.22
Docs: Add Go 1.22 to supported versions range
2024-03-20 14:04:26 +00:00
Michael B. Gale
c74d6348f9 Go: Run go with a valid toolchain version if we have found an invalid one 2024-03-20 13:55:37 +00:00
Michael B. Gale
0d527b2f75 Go: Keep track of all installed toolchains that we know of 2024-03-20 13:52:06 +00:00
Jeroen Ketema
1fd11928eb Merge pull request #15978 from jketema/destructors16
C++: Handle destructors at temporary object lifetime expressions
2024-03-20 14:24:10 +01:00
Ian Lynagh
9086ec8b13 Merge pull request #15973 from igfoo/igfoo/exprs
Kotlin 2: Accept more test changes
2024-03-20 13:13:56 +00:00
Michael B. Gale
96a6dd72cd Go: Move go version command construction into its own function 2024-03-20 13:08:59 +00:00
Michael B. Gale
c71ba0361e Docs: Add Go 1.22 to supported versions range 2024-03-20 12:12:20 +00:00
Mathias Vorreiter Pedersen
c9dbb7c5a9 C++: Rewrite 'cpp/missing-check-scanf' to use standard dataflow configurations. 2024-03-20 12:01:57 +00:00
Michael B. Gale
06134467e9 Go: Make CODEQL_EXTRACTOR_GO_FAST_PACKAGE_INFO true by default 2024-03-20 12:01:49 +00:00
Ian Lynagh
3fa7532b43 Kotlin 2: Accept more test changes 2024-03-20 11:46:58 +00:00
Cornelius Riemenschneider
8fbd743e9e Merge pull request #15971 from github/criemen/bazel-7-1
Upgrade to bazel 7.1
2024-03-20 12:27:03 +01:00
Mathias Vorreiter Pedersen
7ff2998c88 Merge pull request #15980 from MathiasVP/guards-lt
C++: Support `<` reasoning for `switch` statements in Guards library
2024-03-20 10:40:39 +00:00
Mathias Vorreiter Pedersen
3a7b80da47 C++: Respond to review comments. 2024-03-20 10:12:29 +00:00
Mathias Vorreiter Pedersen
9179f0bda6 Merge pull request #15969 from MathiasVP/disable-some-constant-folding
C++: Disable _some_ constant folding in IR
2024-03-20 09:25:06 +00:00
Arthur Baars
1d956e1039 Merge pull request #15974 from github/dbartol/rc3.13-mergeback
Mergeback from `rc/3.13`
2024-03-20 10:13:32 +01:00
Jeroen Ketema
3ee965f2b9 C++: Update test results 2024-03-20 10:05:35 +01:00
Alex Denisov
1cfde49297 Swift: remove unused patches 2024-03-20 09:24:25 +01:00
Alex Denisov
589a5039c8 Swift: update Swift 5.10 dependencies 2024-03-20 09:23:12 +01:00
Tony Torralba
0bb86fc087 Merge pull request #15983 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-03-20 09:00:34 +01:00
Paolo Tranquilli
10efcc2bb4 Swift: add -headerpad_max_install_names to link options 2024-03-20 08:35:33 +01:00
github-actions[bot]
f6f7073520 Add changed framework coverage reports 2024-03-20 00:15:31 +00:00
Mathias Vorreiter Pedersen
97aa301ac9 C++: Accept more test changes. 2024-03-19 17:33:23 +00:00
Mathias Vorreiter Pedersen
88bfb81b1f C++: Add change note. 2024-03-19 17:14:07 +00:00
Taus
d12ac1e7ce Python: Use tsp instead of tree-sitter-python 2024-03-19 17:11:40 +00:00
Taus
38169a981d Python: Shorten tree-sitter-python directory name
The current name results in a path that is more than 260 characters long,
and this causes issues for the build on Windows.
2024-03-19 17:11:40 +00:00
Taus
6f388acdd8 Python: Rename tsg_python_crate_index to py_deps
This aligns us a bit more with Ruby.
2024-03-19 17:11:40 +00:00
Taus
04c9ed37a7 Python: Fix reference in unit test
The referenced file lives in the internal repo, so this is perhaps a bit
of a hack, but I think it should be fine in the short run.
2024-03-19 17:11:40 +00:00
Taus
cac5a8236e Python: Fix CLI integration tests
Two issues:

- Tests relying on existing query machinery (i.e. `import python`) were not resolving
  correctly due to a bad `qlpack.yml` file.
- The diagnostics output tests needed an updated import to account for their new location.
2024-03-19 17:11:40 +00:00
Taus
0550c46766 Python: Fix Bazel build 2024-03-19 17:11:40 +00:00
Taus
5fed8bc57b Python: Add codeql-extractor.yml 2024-03-19 17:11:40 +00:00
Taus
016aedab0a Python: Move Python language pack tooling to external repo
This is essentially the contents of `language-packs/python/tools` with some minor
modifications to account for the changed location.

Of note: we explicitly exclude the `recorded-call-graph-metrics` director that
was already present in `python/tools`. When we revisit this directory for some
cleanup (e.g. to get rid of the `lgtm` references), we'll probably want to switch
to an explicit list of sources to include.
2024-03-19 17:11:40 +00:00
Taus
cdc879ee89 Python: Fix up some bazel references 2024-03-19 17:11:40 +00:00
Mathias Vorreiter Pedersen
1411ee5b26 C++: Extend tests to also test the new predicates and accept test changes. 2024-03-19 17:09:22 +00:00
Mathias Vorreiter Pedersen
a78080cc0e C++: Implement less-than logic for guard conditions when comparing to constants. 2024-03-19 17:06:26 +00:00
Mathias Vorreiter Pedersen
8b85735cdc C++: Generalize predicates from booleans to abstract values. 2024-03-19 17:03:59 +00:00
Dave Bartolomeo
bf46fa27d6 Merge remote-tracking branch 'origin/main' into dbartol/rc3.13-mergeback 2024-03-19 13:02:15 -04:00
Mathias Vorreiter Pedersen
aeb667c6ca Merge pull request #15976 from MathiasVP/guards-eq-follow-up
C++: Fix interface for `GuardCondition.comparesEq` and `GuardCondition.ensuresEq`
2024-03-19 16:45:38 +00:00
Mathias Vorreiter Pedersen
6bf1611f10 C++: Fix comments. 2024-03-19 16:26:37 +00:00
Michael B. Gale
be027e217e Go: Emit diagnostic for invalid toolchain versions 2024-03-19 16:26:06 +00:00
Mathias Vorreiter Pedersen
357a2ba733 C++: Sync identical files. 2024-03-19 16:24:11 +00:00
Mathias Vorreiter Pedersen
458ee13345 C++: Add constant analysis for bitwise operations now that these are no longer constant folded by IR construction. 2024-03-19 16:23:57 +00:00
yoff
ee411cc53a Merge pull request #15936 from yoff/python/test-conflicting-summaries
Python: No `fieldFlowBranchLimit` for `SummarizedCallable`s
2024-03-19 16:56:56 +01:00
Robert Marsh
467f4e11a1 C++: Change note for IR translation of destruction of temporaries with extended lifetimes 2024-03-19 15:55:36 +00:00
Robert Marsh
5a30ad162a C++: Add a comment for ReusedExpr IR translation 2024-03-19 15:54:52 +00:00
Robert Marsh
3d4f7d880d C++: unsuppress destructoion of temporaries with extended lifetimes 2024-03-19 15:54:42 +00:00
Robert Marsh
ba10ea8121 C++: ReuseExpr IR translation 2024-03-19 15:50:28 +00:00
Michael Nebel
d3aa2eed64 C#: Fix test. 2024-03-19 16:30:24 +01:00
Jeroen Ketema
f5fed84bb2 Merge pull request #15968 from jketema/destructors15
C++: Fabricate destructors for temporaries that occur in dynamic initializations
2024-03-19 16:16:43 +01:00
Owen Mansel-Chan
b8608a1b1c Merge pull request #15946 from owen-mc/java/more-manual-models
Java: more manual models
2024-03-19 15:00:27 +00:00
Mathias Vorreiter Pedersen
c640bd67e9 C++: Fix tests for guards. 2024-03-19 14:43:16 +00:00
Mathias Vorreiter Pedersen
6ce3f35ef5 C++: Fix API for guards. 2024-03-19 14:43:10 +00:00
Dave Bartolomeo
311ba8ea1b Merge from main to resolve conflicts 2024-03-19 10:41:31 -04:00
Harry Maclean
219cd4e415 Merge pull request #14426 from hmac/hmac-ar-scopes
Ruby: Track flow into ActiveRecord scopes
2024-03-19 14:19:14 +00:00
Chris Smowton
f8124222cc Merge pull request #15959 from smowton/smowton/admin/jdk22-test-changes
JDK22 upgrade test changes
2024-03-19 14:02:46 +00:00
Harry Maclean
7e479e3c8e Ruby: Fix Hash#keys flow summary 2024-03-19 13:47:45 +00:00
Tom Hvitved
ee3e38f0eb Simplify test interface in FlowSummaryImpl.qll 2024-03-19 14:35:00 +01:00
Owen Mansel-Chan
7371f5e508 Provenance should be "df-manual" 2024-03-19 13:33:49 +00:00
Mathias Vorreiter Pedersen
597f0082e7 Merge pull request #15958 from MathiasVP/ir-guards-from-switch-statements-2
C++: Implement guards logic for switch statements
2024-03-19 13:21:45 +00:00
Michael Nebel
70c6744944 Java/Go/Swift: Sync changes. 2024-03-19 14:20:43 +01:00
Michael Nebel
d24f032d97 C#: Update other tests. 2024-03-19 14:20:43 +01:00
Michael Nebel
b39842501a C#: Update sink test expected output. 2024-03-19 14:20:42 +01:00
Michael Nebel
e32902ad47 C#: Update source expected test output. 2024-03-19 14:20:42 +01:00
Michael Nebel
5b37ee4ec7 Re-factor TestOutput into a param module. 2024-03-19 14:20:42 +01:00
Mathias Vorreiter Pedersen
54262a53c3 Revert "C++: Accept test changes."
This reverts commit f36b48346e.
2024-03-19 13:18:01 +00:00
Mathias Vorreiter Pedersen
a88d8b260d C++: Only ignore constant folding for certain binary operations. 2024-03-19 13:17:49 +00:00
Mathias Vorreiter Pedersen
a97891cbc1 C++: Add QLDoc to 'getNumberOfBinaryOperands' (and rename it to 'getNumberOfNestedBinaryOperands'). 2024-03-19 12:56:15 +00:00
Mathias Vorreiter Pedersen
f36b48346e C++: Accept test changes. 2024-03-19 12:50:43 +00:00
Harry Maclean
df1845379a Merge pull request #15965 from hmac/hmac-symbol-constant
Ruby: remove isString from TSymbol
2024-03-19 12:50:27 +00:00
Michael Nebel
90db9b330f C#: Add MaD source and sink test query to shared library. 2024-03-19 13:45:38 +01:00
Cornelius Riemenschneider
42c5066cae Upgrade to bazel 7.1 2024-03-19 13:40:45 +01:00
Harry Maclean
22ddf2129b Ruby: remove isString from TSymbol 2024-03-19 12:27:34 +00:00
Tom Hvitved
31e04631d1 QL4QL: Regenerate DB scheme and stats 2024-03-19 13:04:12 +01:00
Tom Hvitved
865026f22b Ruby: Add up/downgrade scripts (sigh) 2024-03-19 13:04:12 +01:00
Tom Hvitved
72ff494739 Ruby: Regenerate dbscheme and stats 2024-03-19 13:04:07 +01:00
Mathias Vorreiter Pedersen
1af1ba48a9 C++: Accept test changes. 2024-03-19 11:46:51 +00:00
Mathias Vorreiter Pedersen
4d3076ae7e C++: Don't constant fold small binary operations. 2024-03-19 11:46:51 +00:00
Mathias Vorreiter Pedersen
e16e1c7e83 C++: Add tests. 2024-03-19 11:26:32 +00:00
Jeroen Ketema
06dbb4e9ef Merge pull request #15937 from jketema/destructors14
C++: Handle destructors of temporaries with extended lifetimes
2024-03-19 12:07:05 +01:00
Mathias Vorreiter Pedersen
d7afd7b2e1 C++: Accept test changes. 2024-03-19 10:54:35 +00:00
Mathias Vorreiter Pedersen
350b239ed6 C++: Fix cartesian product in 'simple_comparison_eq'. 2024-03-19 10:29:43 +00:00
Jeroen Ketema
d47e2690b8 C++: Update test results after extractor changes 2024-03-19 11:18:36 +01:00
Jeroen Ketema
fd49871b9a C++: Handle destructors of temporaries with extended lifetimes 2024-03-19 10:56:44 +01:00
Tom Hvitved
cee6f003fd Tree-sitter: Split up ast_node_info table into two tables 2024-03-19 10:52:37 +01:00
Mathias Vorreiter Pedersen
0c3d9f75f4 C++: Add change note. 2024-03-19 09:41:58 +00:00
yoff
f025430431 Merge pull request #15319 from Sim4n6/main
[Python] Add Unicode DoS (qhelp, tests and the query)
2024-03-19 10:00:30 +01:00
Rasmus Wriedt Larsen
d78efdb67b Merge pull request #15883 from RasmusWL/js-cg-tests
JS: show test changes after #15823
2024-03-19 09:58:20 +01:00
Harry Maclean
dde148ee7e Ruby: add changenote 2024-03-19 08:40:30 +00:00
Harry Maclean
32b80f8cb1 Ruby: Add tests for hash flow 2024-03-19 08:38:14 +00:00
Tom Hvitved
5ab1047b14 Merge pull request #15882 from hvitved/js/dataflow-node-get-location
JS: Add `DataFlow::Node.getLocation`
2024-03-19 09:21:00 +01:00
Chris Smowton
9a8ec36a4f Accept test changes 2024-03-19 07:55:08 +00:00
Mathias Vorreiter Pedersen
aa1d5c5e41 Merge pull request #15960 from MathiasVP/unitialized-local-as-path
C++: Convert `cpp/uninitialized-local` to a `path-problem` query
2024-03-18 21:18:17 +00:00
Erik Krogh Kristensen
a3da6c886b Merge pull request #15895 from erik-krogh/url-java-qhelp
Java: update the url-redirection in the same style as the C# qhelp
2024-03-18 21:10:07 +01:00
yoff
44ab36f238 Merge pull request #15729 from yoff/python/hardcoded-credentials-without-pointsto
python: Rewrite `HardcodedCredentials` away from `PointsTo`
2024-03-18 20:48:30 +01:00
Tom Hvitved
fc55567d90 Merge pull request #15853 from hvitved/dataflow/get-location
Data flow: Replace `hasLocationInfo` with `getLocation`
2024-03-18 20:21:46 +01:00
Tom Hvitved
8899d66132 Merge pull request #15734 from hvitved/dataflow/hidden-subpath
Data flow: Account for hidden `subpath` wrappers
2024-03-18 20:17:16 +01:00
Michael B. Gale
3649af3f05 Go: Add test for go/autobuilder/invalid-go-toolchain-version diagnostic 2024-03-18 17:56:59 +00:00
Harry Maclean
187a68bf76 Ruby: Add flow summary for Hash#keys 2024-03-18 17:56:10 +00:00
Harry Maclean
e895f96a3a Ruby: Taint flow to second block param in map
When `map` is called on a hash, the values in the hash are passed to the
second parameter of the block.
2024-03-18 17:55:02 +00:00
Mathias Vorreiter Pedersen
b66b8785c4 Merge branch 'main' into unitialized-local-as-path 2024-03-18 17:42:53 +00:00
Chris Smowton
35a309fd40 Merge pull request #15897 from smowton/smowton/admin/test-for-gradle-wrapper-without-gradle
Java: add test for partial gradle wrapper without gradle on the path
2024-03-18 17:07:20 +00:00
Owen Mansel-Chan
764e99bda7 Fix model for java.util.Scanner#findall(String)
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2024-03-18 16:56:20 +00:00
Owen Mansel-Chan
e10ce8875f Merge pull request #15947 from owen-mc/java/fix-model-provenance-to-df-manual
Fix model provenance to df-manual
2024-03-18 16:54:39 +00:00
Mathias Vorreiter Pedersen
9c2b2160ce Merge pull request #15939 from MathiasVP/experimental-surprising-lifetimes-for-range-based-for-loop
C++: Add an experimental query for surprising lifetimes from range-based for loops
2024-03-18 16:43:11 +00:00
Mathias Vorreiter Pedersen
40dbc6fdd9 C++: Accept test changes. 2024-03-18 16:27:18 +00:00
Mathias Vorreiter Pedersen
032678a367 C++: Extend tests to also test the new predicates. 2024-03-18 16:27:10 +00:00
Mathias Vorreiter Pedersen
dbd47b387a C++: Add AST wrappers for the new predicates. 2024-03-18 16:26:36 +00:00
Mathias Vorreiter Pedersen
decede51dc C++: Use the new predicate in 'ScanfChecks.qll'. 2024-03-18 16:07:57 +00:00
Mathias Vorreiter Pedersen
44045d3eed C++: Add guards logic for constant comparisons. 2024-03-18 16:07:57 +00:00
Mathias Vorreiter Pedersen
a21eea4ee0 C++: Generalize more predicates from booleans to abstract values. 2024-03-18 16:07:57 +00:00
Arthur Baars
e812682991 Merge pull request #15955 from github/post-release-prep/codeql-cli-2.16.5
Post-release preparation for codeql-cli-2.16.5
2024-03-18 16:58:01 +01:00
Mathias Vorreiter Pedersen
b944f3b411 C++: Fix FP. 2024-03-18 15:57:20 +00:00
Mathias Vorreiter Pedersen
e373341f62 C++: Add more tests. 2024-03-18 15:57:17 +00:00
Ian Lynagh
60b5e49905 Java: Limit the amount of results that MissingEnumInSwitch produces per switch
The tool status page warns:
    An analysis file contained multiple alerts that included more related
    locations than our allowed limit of 100.
    These alerts correspond to the rule java/missing-case-in-switch.
    Only 100 locations were stored for these alerts.
2024-03-18 15:56:21 +00:00
Ian Lynagh
916b1e959e Java: Add a test for MissingEnumInSwitch 2024-03-18 15:56:10 +00:00
Chris Smowton
af7b1bc425 Java: add test for partial gradle wrapper without gradle on the path
Note I had to mimic the actual absence of Gradle by testing the case where it fails, but have manually verified a missing binary works too.
2024-03-18 15:37:39 +00:00
Mathias Vorreiter Pedersen
668239f355 C++: Convert tabs to spaces. 2024-03-18 15:16:10 +00:00
Mathias Vorreiter Pedersen
bd0969b87b C++: Add change note. 2024-03-18 15:04:19 +00:00
Mathias Vorreiter Pedersen
4a55b6fbdf C++: Make 'cpp/uninitialized-local' a path-problem query. 2024-03-18 15:02:33 +00:00
Harry Maclean
80ae017aa1 Ruby: Track flow into ActiveRecord scopes 2024-03-18 15:01:37 +00:00
Tom Hvitved
0cecbf5239 Update 2024-02-28-hidden-subpaths.md
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2024-03-18 15:36:01 +01:00
Joe Farebrother
4177c38ed4 Merge pull request #15907 from joefarebrother/ruby-uploaded-file
Ruby: Model ActiveDispatch::Http::UploadedFile
2024-03-18 14:02:33 +00:00
Tamas Vajk
322fb6c507 Change integration test to return stable results 2024-03-18 14:53:49 +01:00
Tom Hvitved
7a3b8ebb3a Address review comments 2024-03-18 14:49:35 +01:00
Tom Hvitved
40089e8088 Add change note 2024-03-18 14:49:35 +01:00
Tom Hvitved
e53357d376 Update expected test output 2024-03-18 14:49:32 +01:00
Tom Hvitved
d7c9bfa08b Data flow: Account for hidden subpath wrappers 2024-03-18 14:47:11 +01:00
Sim4n6
1af8167354 updated the .expected file 2024-03-18 13:26:20 +00:00
Tamas Vajk
d749335f54 C#: Limit extracted compilation and extraction messages 2024-03-18 14:24:34 +01:00
Tom Hvitved
d83500de5d Address review comments 2024-03-18 14:24:07 +01:00
Tamas Vajk
e8e1dc0390 C#: Add integration test with extraction and compilation messages 2024-03-18 14:23:40 +01:00
github-actions[bot]
aebe9f6992 Post-release preparation for codeql-cli-2.16.5 2024-03-18 12:16:26 +00:00
Rasmus Wriedt Larsen
c82f5dad56 JS: show test changes after #15823 2024-03-18 13:09:37 +01:00
Rasmus Wriedt Larsen
28c3d35e9b Merge commit '7c35309732dd2aa4dc0b4e2949922272ad448854' into js-cg-tests 2024-03-18 13:08:46 +01:00
Rasmus Wriedt Larsen
f9309cec0b JS: Add tests before #15823 changes 2024-03-18 13:08:39 +01:00
Mathias Vorreiter Pedersen
7b6accd33a Update cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2024-03-18 12:01:51 +00:00
Mathias Vorreiter Pedersen
457d71d7bc Update cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2024-03-18 12:01:44 +00:00
Arthur Baars
dbf16827bf Merge pull request #15951 from github/aibaars/changenotes-fixes
Fix minor formatting issues in changenotes
2024-03-18 12:56:50 +01:00
Tamás Vajk
7429fa7b96 Merge pull request #15952 from tamasvajk/buildless/impr1
C#: Add logging for source file parsing
2024-03-18 12:27:27 +01:00
Tamás Vajk
f63c9fa07f Merge pull request #15953 from tamasvajk/buildless/impr2
C#: Iterate text files only once
2024-03-18 12:26:38 +01:00
Ian Lynagh
d2bb951ecd Merge pull request #15943 from igfoo/igfoo/k2locs
Kotlin 2: Accept more location changes
2024-03-18 11:26:08 +00:00
Owen Mansel-Chan
7fb05f4a76 Fix duplicate "df-" in "df-df-manual" 2024-03-18 11:17:55 +00:00
Mathias Vorreiter Pedersen
575af1a5f9 Merge branch 'main' into experimental-surprising-lifetimes-for-range-based-for-loop 2024-03-18 11:11:32 +00:00
Mathias Vorreiter Pedersen
1d12e0c9d9 Merge pull request #15941 from MathiasVP/ir-guards-from-switch-statements
C++: Handle `switch` statements in the guards library
2024-03-18 11:07:10 +00:00
Mathias Vorreiter Pedersen
e0476b555d Merge pull request #15934 from MathiasVP/ir-models-for-iterators
C++: Add alias and side-effect models to `begin` and `end` functions
2024-03-18 11:06:59 +00:00
Arthur Baars
769e3469a4 Merge pull request #15954 from github/release-prep/2.16.5
Release preparation for version 2.16.5
2024-03-18 11:56:14 +01:00
Mathias Vorreiter Pedersen
0be329dbdc C++: Delete duplicated code. 2024-03-18 10:33:40 +00:00
github-actions[bot]
0a6243d07b Release preparation for version 2.16.5 2024-03-18 10:14:07 +00:00
Mathias Vorreiter Pedersen
51db2b0bc4 C++: Convert tabs to spaces in ir.cpp. 2024-03-18 10:11:37 +00:00
Tamas Vajk
881c426631 C#: Iterate text files only once 2024-03-18 11:06:44 +01:00
Tamas Vajk
3a8d468983 C#: Add logging for source file parsing 2024-03-18 11:02:29 +01:00
Arthur Baars
a810165e35 Fix minor formatting issues in changenotes 2024-03-18 10:57:05 +01:00
Tom Hvitved
a13391bda1 Merge pull request #15802 from hvitved/dataflow/variable-capture-overlapping-paths
Variable capture: Avoid overlapping and false-positive data flow paths
2024-03-18 10:45:55 +01:00
Rasmus Lerchedahl Petersen
2a0c451d2d python: No fieldFlowBranchLimit for SummarizedCallables
Like https://github.com/github/codeql/pull/15689 for Ruby.
2024-03-18 10:29:36 +01:00
Rasmus Lerchedahl Petersen
45c65b48aa python: make it a real package
so python2 also respects it
2024-03-18 08:49:31 +01:00
Jami Cogswell
a8eb1d10f6 Java: remove experimental tests 2024-03-17 22:35:27 -04:00
Jami Cogswell
658fffeac1 Java: remove experimental files 2024-03-17 22:03:59 -04:00
Owen Mansel-Chan
754d4cd959 Fix model provenance to df-manual 2024-03-17 14:36:47 +00:00
Owen Mansel-Chan
23a58a0835 Add df-manual models related to existing df-manual models 2024-03-17 14:21:05 +00:00
Owen Mansel-Chan
fc367042ef Fix df-manual model with wrong parameter type 2024-03-17 14:21:01 +00:00
Ian Lynagh
a53d5d832d Kotlin 2: Accept more loc changes 2024-03-15 18:08:53 +00:00
Ian Lynagh
c4c843968e Kotlin 2: Accept more loc changes 2024-03-15 18:07:39 +00:00
Ian Lynagh
57d17d85f2 Kotlin 2: Accept more loc changes 2024-03-15 18:07:12 +00:00
Ian Lynagh
6c0885c24d Kotlin 2: Accept more loc changes 2024-03-15 18:06:45 +00:00
Jami Cogswell
55f7369df0 Java: performance fix 2024-03-15 14:06:36 -04:00
Ian Lynagh
5580daf60e Kotlin 2: Accept more loc changes 2024-03-15 18:06:13 +00:00
Ian Lynagh
1d2b31f0be Kotlin 2: Accept more loc changes 2024-03-15 18:05:46 +00:00
Ian Lynagh
5552fe3c34 Kotlin 2: Accept more loc changes 2024-03-15 18:05:09 +00:00
Ian Lynagh
28f98d0344 Kotlin 2: Accept more location changes 2024-03-15 18:04:28 +00:00
Ian Lynagh
354cdf44aa Kotlin 2: Accept more location changes 2024-03-15 18:03:55 +00:00
Ian Lynagh
f4542f6160 Kotlin2 : Accept some more location changes 2024-03-15 18:02:54 +00:00
Mathias Vorreiter Pedersen
e23e3d7fb4 C++: Run tests without the extractor and analysis changes. 2024-03-15 17:35:47 +00:00
Mathias Vorreiter Pedersen
a8718f99a1 C++: Add qhelp for 'cpp/iterator-to-expired-container'. 2024-03-15 17:35:47 +00:00
Mathias Vorreiter Pedersen
3a8db49573 C++: Add tests for 'cpp/iterator-to-expired-container'.
NOTE: This is with the yet-to-be-merged changes to the extractor and IR generation.
2024-03-15 17:35:17 +00:00
Mathias Vorreiter Pedersen
f4f417c3f9 C++: Fix QLoc. 2024-03-15 17:19:36 +00:00
Mathias Vorreiter Pedersen
b5e59492bf C++: Add change note. 2024-03-15 17:17:05 +00:00
Mathias Vorreiter Pedersen
fb218150e1 C++: Change the testcase so that it outputs the controlling values for switch statements as well. 2024-03-15 17:05:42 +00:00
Mathias Vorreiter Pedersen
07ebbb0591 C++: Accept test changes. 2024-03-15 17:04:27 +00:00
Mathias Vorreiter Pedersen
34decd3cf1 C++: Add more general public predicates to work with abstract values. 2024-03-15 17:03:45 +00:00
Mathias Vorreiter Pedersen
f4eb5f5a2d C++: Convert 'getBranchSuccessor' to use abstract values. 2024-03-15 17:03:45 +00:00
Mathias Vorreiter Pedersen
b7292fbc67 C++: Introduce 'AbstractValue' similar to what C# has. 2024-03-15 17:03:45 +00:00
Mathias Vorreiter Pedersen
2af68d37d0 C++: Include 'SwitchInstruction's as 'IRGuardCondition's. 2024-03-15 17:03:45 +00:00
Mathias Vorreiter Pedersen
704f1fad46 C++: Add switches as testcases for guard conditions. 2024-03-15 17:02:32 +00:00
Max Schaefer
daee22d38c Merge pull request #15933 from github/max-schaefer/go-incomplete-hostname-regex
Go: Mention raw string iterals in QHelp for `go/incomplete-hostname-regexp`.
2024-03-15 15:07:10 +00:00
Edward Minnix III
8ae64e992c Merge pull request #15929 from egregius313/egregius313/csharp/mad/source-node-clases-for-models
C#: Add classes extending `SourceNode` for local and stored source models
2024-03-15 11:06:14 -04:00
Joe Farebrother
8c5fff2d11 Update names and qldoc for params taint predicates 2024-03-15 14:43:29 +00:00
Mathias Vorreiter Pedersen
23cf99734a C++: Add a new experimental query ' cpp/iterator-to-expired-container'. 2024-03-15 14:29:29 +00:00
Mathias Vorreiter Pedersen
f7c29e6bfb C++: Expose some previously private classes from our models so they can be used in queries. 2024-03-15 14:21:39 +00:00
Rasmus Lerchedahl Petersen
cfbc3f73ec Pyhton: add test for conflicting summaries
We noticed that when
- a function has more than one summary (with different charpred)
- one summary is subsumed by a subpath (or something happens around the function being extracted)
- the function is called multiple times(we needed at least three)
one of the summaries would no longer lead to flow.
2024-03-15 15:13:39 +01:00
Sim4n6
3acdd3382c Update the expected file 2024-03-15 14:17:23 +01:00
Sim4n6
26a16b7857 use of a single var "op" of type Cmpop 2024-03-15 14:17:23 +01:00
Sim4n6
a717bf1b9d Fix p tag in UnicodeDoS.qhelp 2024-03-15 14:17:23 +01:00
Sim4n6
af19a0342e Fix UnicodeDoS vulnerability in CWE-770 code 2024-03-15 14:17:23 +01:00
Sim4n6
085d803b14 Fix UnicodeDoS vulnerability in CWE-770 2024-03-15 14:17:23 +01:00
Sim4n6
31dc542111 Update request parameter name in good_1() function 2024-03-15 14:17:23 +01:00
Sim4n6
70ebc58b4c Refactor Unicode normalization code 2024-03-15 14:17:23 +01:00
Sim4n6
3d8868a6c3 Add routes for bad_5 and bad_6, and fix routes for good_3 and good_4 2024-03-15 14:17:23 +01:00
Sim4n6${{7*'7'}}
658b88e62f Update python/ql/src/experimental/Security/CWE-770/UnicodeDoS.ql
update the Config API

Co-authored-by: yoff <lerchedahl@gmail.com>
2024-03-15 14:17:23 +01:00
Sim4n6
1f767b887e Add some comments and docs 2024-03-15 14:17:23 +01:00
Sim4n6
5cc9170249 Add UnicodeDoS sink for werkzeug secure_filename 2024-03-15 14:17:23 +01:00
Sim4n6
342465057c Add Unicode DoS (CWE-770) 2024-03-15 14:17:23 +01:00
Mathias Vorreiter Pedersen
19c9ea7e20 C++: Implement alias and side effect models for iterators. 2024-03-15 12:13:43 +00:00
Mathias Vorreiter Pedersen
a51fe4a00e C++: Make the vector and iterator classes in 'ir.cpp' more realistic. This matches the one we use for dataflow tests. 2024-03-15 12:10:48 +00:00
Max Schaefer
d3e0a90ae5 Go: Mention raw string iterals in QHelp for go/incomplete-hostname-regexp. 2024-03-15 11:22:40 +00:00
Tom Hvitved
693c28a821 Merge pull request #15931 from hvitved/ql/remove-missing-override-query
QL4QL: Remove `MissingOverride` query
2024-03-15 11:28:41 +01:00
Owen Mansel-Chan
8e52483beb Add df-manual models in manually modeled classes 2024-03-15 10:10:23 +00:00
Tom Hvitved
80649786c3 QL4QL: Remove MissingOverride query 2024-03-15 11:06:15 +01:00
Tom Hvitved
e7b00a7b42 Ruby: Add post-update argument nodes for string constants 2024-03-15 10:47:39 +01:00
Tony Torralba
171ff4d161 Merge pull request #15928 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-03-15 09:24:57 +01:00
Ed Minnix
71cf948650 Classes extending SourceNode for local and stored source models
Queries such as `cs/sql-injection` cast their source to a `SourceNode`
in order to describe them. For example:

```ql
import semmle.code.csharp.security.dataflow.flowsources.FlowSources

string getSourceType(DataFlow::Node source) {
   result = source.(SourceNode).getSourceType()
}
```

Models as data source models are not included in `SourceNode` by
default, they must be wrapped with a class extending `SourceNode`.

This adds such classes, which wrap the
`sourceNode(DataFlow::Node,string)` predicate and assigns a
`getSourceType`.
2024-03-14 22:23:54 -04:00
github-actions[bot]
7f05743212 Add changed framework coverage reports 2024-03-15 00:16:16 +00:00
Joe Farebrother
f464f1b94e Accept test output + fix qldoc typo 2024-03-14 22:25:37 +00:00
Joe Farebrother
b4ed77343b Add change note + fix qldoc 2024-03-14 22:25:36 +00:00
Joe Farebrother
3e61be1b6a Add test cases 2024-03-14 22:25:36 +00:00
Joe Farebrother
5333c75919 Model additional string attributes 2024-03-14 22:25:36 +00:00
Joe Farebrother
8c31b612ca Model UploadedFile original_filename and read 2024-03-14 22:25:35 +00:00
Mathias Vorreiter Pedersen
6dddae0154 Merge pull request #15925 from MathiasVP/rename-dataflowutil-class
C++: Follow-up to #15918
2024-03-14 18:15:14 +00:00
Tony Torralba
ee3efbadae Merge pull request #15924 from atorralba/atorralba/go/hardcoded-credentials-fix
Go: Consider more strings as hardcoded credentials
2024-03-14 16:52:34 +01:00
Tamás Vajk
945121de1b Merge pull request #15922 from tamasvajk/buildless/namespace-extraction
C#: Handle namespace resolution error more gracefully
2024-03-14 16:19:48 +01:00
Michael Nebel
2280469564 Merge pull request #15902 from michaelnebel/csharp/uncontrolledformatstring
C#: Remove hard-coded local sources from the uncontrolled-format-string query.
2024-03-14 15:21:31 +01:00
Mathias Vorreiter Pedersen
7fdea27d33 C++: Rename 'IndirectTemporaryExpr' to 'IndirectOperandExprNode'. 2024-03-14 11:46:15 +00:00
Owen Mansel-Chan
2bd08838d4 Add manual neutral models for java.lang.ClassLoader 2024-03-14 11:40:06 +00:00
Owen Mansel-Chan
5b734c76b6 Add manual neutral models for java.util.Locale and its subclasses 2024-03-14 11:39:59 +00:00
Tony Torralba
20691e409c Add change note 2024-03-14 11:56:43 +01:00
Mathias Vorreiter Pedersen
9aefdca7a7 Merge pull request #15875 from MathiasVP/bring-back-type-barriers-in-non-constant-format
C++: Clean up `cpp/non-constant-format`
2024-03-14 10:51:23 +00:00
Tony Torralba
30d906d42a Merge pull request #15906 from atorralba/atorralba/java/jdk-neutrals
Java: Add more neutral JDK models
2024-03-14 11:07:06 +01:00
Mathias Vorreiter Pedersen
dacf7d73d9 Merge pull request #15918 from MathiasVP/fix-as-expr-for-temps
C++: Fix dataflow node <> expression problem on prvalues
2024-03-14 09:38:46 +00:00
Tony Torralba
87b2dcc892 Adjust test expectations 2024-03-14 10:25:04 +01:00
Mathias Vorreiter Pedersen
a24432bacc Update cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll 2024-03-14 09:23:33 +00:00
Mathias Vorreiter Pedersen
c375497fa5 Update cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll 2024-03-14 09:16:04 +00:00
Tony Torralba
d8c0ab8e1f Go: Consider more strings as hardcoded credentials 2024-03-14 10:11:39 +01:00
Tony Torralba
9d44045e6f Adjust test expectations 2024-03-14 09:41:34 +01:00
Tony Torralba
eecab9122a Recognize the model generator involvement in the models' provenances 2024-03-14 08:56:23 +01:00
Tony Torralba
5b88b8a3ed A few more neutrals 2024-03-14 08:53:58 +01:00
Tony Torralba
36f6a6fb10 Model more EnumSet methods as neutrals 2024-03-14 08:46:43 +01:00
Tamas Vajk
b5f349bd2c C#: Handle namespace resolution error more gracefully 2024-03-14 08:37:22 +01:00
Jeroen Ketema
b2e0485c94 Merge pull request #15908 from jketema/destructors12
C++: suppress destructors with reuse expressions until proper support is added
2024-03-14 07:41:59 +01:00
Mathias Vorreiter Pedersen
a839c92979 C++: Fix mapping issue between dataflow nodes and expressions when the expression is a prvalue. 2024-03-13 22:59:09 +00:00
Mathias Vorreiter Pedersen
2fc0922b29 Merge branch 'main' into bring-back-type-barriers-in-non-constant-format 2024-03-13 22:46:35 +00:00
Mathias Vorreiter Pedersen
d1c253b519 C++: Accept test changes. 2024-03-13 22:41:32 +00:00
Mathias Vorreiter Pedersen
61597f5ac7 C++: This commit does two things:
1. It fixes a logic error in the cannotContainString predicate.
2. It reverts the changes to the `isSource` predicate that required the external
function to be within the source root.

The change to `isSource` was meant to fix the a performance problem that occurred
because of the logic error in the cannotContainString predicate. However, now that
the logic error is fixed this is no longer necessary 🎉
2024-03-13 22:40:06 +00:00
erik-krogh
ef8368cfc4 fix typo 2024-03-13 22:37:13 +01:00
Jami Cogswell
1b01f26d09 Java: adjust BarrierPrefix to handle prepended chars 2024-03-13 16:28:45 -04:00
Jami Cogswell
5ac453eb38 Java: add spurious test case for StringBuilder.append 2024-03-13 16:28:45 -04:00
Jami Cogswell
04d27f2d65 Java: adjust prefix barriers 2024-03-13 16:28:44 -04:00
Jami Cogswell
e99cea340b Java: update UrlPathBarrier to include FollowsBarrierPrefix 2024-03-13 16:28:44 -04:00
Jami Cogswell
c5a59d6c51 Java: add QLDoc 2024-03-13 16:28:44 -04:00
Jami Cogswell
7310c155e2 Java: rename SpringUrlForwardSink 2024-03-13 16:28:44 -04:00
Jami Cogswell
a002674587 Java: clean up comments on test cases 2024-03-13 16:28:44 -04:00
Jami Cogswell
a8075969d8 Java: add QLDocs to UrlPathBarrier code 2024-03-13 16:28:44 -04:00
Jami Cogswell
042dcf9cd9 Java: some updates to UrlPathBarrier code 2024-03-13 16:28:44 -04:00
Jami Cogswell
052452b186 Java: create UrlDecodeMethod 2024-03-13 16:28:44 -04:00
Jami Cogswell
d220b3a298 Java: some updates to test cases 2024-03-13 16:28:43 -04:00
Jami Cogswell
d9772c1880 Java: update change note 2024-03-13 16:28:43 -04:00
Jami Cogswell
43b49628fc Java: use new 'SimpleTypeSanitizer', and update some non-extending subtype relationships 2024-03-13 16:28:43 -04:00
Jami Cogswell
2708e53c7f Java: remove redundant imports 2024-03-13 16:28:43 -04:00
Jami Cogswell
f573032b2e Java: remove todo comments from ext files 2024-03-13 16:28:43 -04:00
Jami Cogswell
911a61df22 Java: initial update of barrier and test cases to remove FN 2024-03-13 16:28:42 -04:00
Jami Cogswell
c8ec301793 Java: add change note 2024-03-13 16:28:42 -04:00
Jami Cogswell
e75c96c0f9 Java: combine test cases; add test for StaplerResponse.forward 2024-03-13 16:28:41 -04:00
Jami Cogswell
5fa63ab5c2 Java: update/add some TODO comments 2024-03-13 16:28:41 -04:00
Jami Cogswell
c331393cfd Java: update qhelp 2024-03-13 16:28:41 -04:00
Jami Cogswell
09bc21dbd3 Java: rename 'UnsafeUrlForward' to 'UrlForward' 2024-03-13 16:28:41 -04:00
Jami Cogswell
6e7c05467b Java: update query metadata and alert message 2024-03-13 16:28:41 -04:00
Jami Cogswell
5a9d7552b3 Java: add some comments and minor code reorg 2024-03-13 16:28:41 -04:00
Jami Cogswell
1da1e896cb Java: convert SpringModelAndViewSink to MaD 2024-03-13 16:28:41 -04:00
Jami Cogswell
8d66097483 Java: switch StaplerResponse.forward from request-forgery sink to url-forward sink 2024-03-13 16:28:41 -04:00
Jami Cogswell
42e3825ea3 Java: convert RequestDispatcherSink to MaD 2024-03-13 16:28:40 -04:00
Jami Cogswell
4ff884e26c Java: remove more path-injection related classes (will maybe add some of these back in a separate PR) 2024-03-13 16:28:40 -04:00
Jami Cogswell
2a682995ae Java: move MaD models to correct files, delete ones that already exist 2024-03-13 16:28:40 -04:00
Jami Cogswell
915e106ab3 Java: remove path-injection related models and tests for now 2024-03-13 16:28:40 -04:00
Jami Cogswell
35a083ae9e Java: update test cases to use inline expectations 2024-03-13 16:28:40 -04:00
Jami Cogswell
2793f28428 Java: move config to Query.qll file 2024-03-13 16:28:40 -04:00
Jami Cogswell
0d38a9625e Java: copy files from experimental 2024-03-13 16:28:39 -04:00
Jeroen Ketema
866a3934d4 C++: suppress destructors with reuse expressions until proper support is added 2024-03-13 20:17:00 +01:00
Tom Hvitved
54fa8181da Address review comment 2024-03-13 20:03:01 +01:00
Jeroen Ketema
67b3670d06 Merge pull request #15901 from jketema/destructors11
C++: Introduce re-use expressions in the database scheme
2024-03-13 18:27:28 +01:00
Tony Torralba
039bea1625 Java: Add more neutral JDK models
This is similar to https://github.com/github/codeql/pull/15766, in the sense that it adds neutral models to prevent the model generator from generating summaries for them. These models were spotted while evaluating https://github.com/github/codeql/pull/14919.
2024-03-13 16:59:38 +01:00
Mathias Vorreiter Pedersen
b638d4d0ba Merge pull request #15900 from MathiasVP/glib-alloc-and-dealloc
C++: Add models for `GLib` allocation and deallocation
2024-03-13 15:29:46 +00:00
Erik Krogh Kristensen
bd121b98ae Merge pull request #15893 from erik-krogh/more-filter-taint
JS: allow more flow through .filter()
2024-03-13 16:19:28 +01:00
Rasmus Lerchedahl Petersen
533b63743b Python: test MaD syntax for keyword argument
use the combined positional/keyword syntax as
that is what we will probably mostly use.
2024-03-13 15:28:34 +01:00
Tom Hvitved
6c0ed28e6b Python: Implement new data flow interface 2024-03-13 14:41:57 +01:00
Tom Hvitved
02ae2d1520 Java: Implement new data flow interface 2024-03-13 14:41:57 +01:00
Tom Hvitved
e4a4c18166 Go: Implement new data flow interface 2024-03-13 14:41:57 +01:00
Michael Nebel
560b355e0c C#: Remove hard-coded local sources from the uncontrolled-format-string query. 2024-03-13 14:26:30 +01:00
Erik Krogh Kristensen
53502a8662 Merge pull request #15510 from yoff/ts-54
JS: Add support for TS 5.4
2024-03-13 14:22:24 +01:00
Jeroen Ketema
8d5eab401d C++: Introduce re-use expressions in the database scheme 2024-03-13 13:28:27 +01:00
Tom Hvitved
16cef92106 JS: Add DataFlow::Node.getLocation 2024-03-13 13:06:16 +01:00
Mathias Vorreiter Pedersen
8d504d8b32 Merge pull request #15899 from jketema/destructors10
C++: Add IR tests for the destruction of temporaries
2024-03-13 11:56:04 +00:00
Mathias Vorreiter Pedersen
465c3c18e3 C++: Add change note. 2024-03-13 11:49:26 +00:00
Asger F
c5a02dae2b Merge pull request #15768 from asgerf/js/amd-pseudo-deps
JS: Do not treat AMD pseudo-dependencies as imports
2024-03-13 12:49:17 +01:00
Mathias Vorreiter Pedersen
3ea39a2553 C++: Add some query tests. 2024-03-13 11:39:34 +00:00
Mathias Vorreiter Pedersen
bcd36b1994 C++: Recognize glib allocations and deallocations. 2024-03-13 11:39:15 +00:00
Ian Lynagh
adefdfd59f Merge pull request #15889 from igfoo/igfoo/k2exprs
Kotlin 2: Accept more changes in the exprs test
2024-03-13 11:34:10 +00:00
erik-krogh
129286aa1c allow more flow through .filter() 2024-03-13 12:03:00 +01:00
Jeroen Ketema
3ef1ab49ea C++: Add IR tests for the destruction of temporaries 2024-03-13 12:00:02 +01:00
erik-krogh
013ed7adb3 Java: update the url-redirection in the same style as the C# qhelp 2024-03-13 11:58:16 +01:00
yoff
b5c0fbb827 Merge pull request #15776 from RasmusWL/tt-consistency
Python: Add type-tracking consistency query
2024-03-13 11:11:07 +01:00
Tom Hvitved
4085c8ec8f Merge pull request #15866 from hvitved/ruby/orm-tracking-ap-limit
Ruby: Lower access path limit to 1 for `OrmTracking`
2024-03-13 10:57:09 +01:00
Harry Maclean
dd5eb982ec Merge pull request #15524 from hmac/hmac-process-spawn
Ruby: Add some more command injection sinks
2024-03-13 09:53:10 +00:00
Tony Torralba
2fd2b4c874 Merge pull request #15891 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-03-13 09:51:22 +01:00
github-actions[bot]
cff2cdb9e4 Add changed framework coverage reports 2024-03-13 00:15:53 +00:00
Edward Minnix III
c190dd21db Merge pull request #15877 from egregius313/egregius313/csharp/mad/sources/windows-registry
C#: Add source models for values from the Windows registry
2024-03-12 16:41:42 -04:00
Edward Minnix III
d54489931c Merge pull request #15869 from egregius313/egregius313/java/fix/parcelfiledescriptor-open-sink
Java: Add path-injection sink for `ParcelFileDescriptor::open`
2024-03-12 16:39:20 -04:00
Erik Krogh Kristensen
863e3f79e5 Merge pull request #15731 from erik-krogh/java-url
Java: More sanitizers for request-forgery
2024-03-12 19:31:52 +01:00
Ian Lynagh
0e94aa0eb5 Kotlin 2: Accept more changes in the exprs test 2024-03-12 16:42:37 +00:00
Ian Lynagh
8d1ee10981 Merge pull request #15876 from igfoo/igfoo/buildless-java-complete
Java: Accept test changes
2024-03-12 16:12:58 +00:00
Tamás Vajk
be2ce17376 Merge pull request #15881 from tamasvajk/buildless/fix-fallback
C#: Deduplicate not yet restored package names
2024-03-12 16:08:16 +01:00
Mathias Vorreiter Pedersen
ab6e2f9364 C++: Accept test regression. 2024-03-12 15:04:49 +00:00
erik-krogh
f613823047 add explicit QLDoc that any method named "contains" is matched 2024-03-12 15:25:27 +01:00
erik-krogh
35aae0a981 move changenote to src/ 2024-03-12 15:22:57 +01:00
Erik Krogh Kristensen
b53ae77c56 expand change-note
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2024-03-12 15:22:17 +01:00
Mathias Vorreiter Pedersen
51f5740707 C++: Exclude functions that aren't declared inside the source root. This fixes performance on ImageMagick. 2024-03-12 14:20:16 +00:00
Mathias Vorreiter Pedersen
6a563c161e C++: Simplify the definition of 'isNonConst'. On ImageMagick I get the same exact sources before and after. 2024-03-12 14:20:09 +00:00
Mathias Vorreiter Pedersen
179a7d500e C++: Handle 'wchar_t' types that may be defined as unsigned short in C. This brings back SAMATE results. 2024-03-12 14:19:48 +00:00
Tamas Vajk
b07b0762f2 Adjust based on code review feedback 2024-03-12 15:07:58 +01:00
erik-krogh
74876ff49b add change-note 2024-03-12 15:07:36 +01:00
erik-krogh
52f71e4553 small fixes based on review 2024-03-12 15:07:29 +01:00
Ian Lynagh
c2aa334465 Java: Accept test changes 2024-03-12 14:03:02 +00:00
Tom Hvitved
695e728ed5 Ruby: Lower access path limit to 1 for OrmTracking 2024-03-12 14:58:29 +01:00
Tom Hvitved
dddba3228b Merge pull request #15867 from hvitved/dataflow/ap-limit
Data flow: Add `ConfigSig::accessPathLimit`
2024-03-12 14:57:51 +01:00
erik-krogh
6be0ed1dc3 narrow the version specifier used for TypeScript 2024-03-12 13:42:58 +01:00
Tom Hvitved
d7790faece Address review comments 2024-03-12 13:34:55 +01:00
erik-krogh
95a5ec7f27 add test that the new Object.groupBy method has a type 2024-03-12 13:22:11 +01:00
Michael Nebel
50851210ea Merge pull request #15794 from michaelnebel/csharp/removecil
C#: Delete the CIL extractor.
2024-03-12 12:48:41 +01:00
Mathias Vorreiter Pedersen
1a42e55095 Merge pull request #15820 from MathiasVP/add-type-confusion-query
C++: Add a new query for detecting type confusion vulnerabilities
2024-03-12 10:29:22 +00:00
Tom Hvitved
0e0b73a5e6 Address review comment 2024-03-12 11:22:04 +01:00
Michael Nebel
eb62c033aa C#: Remove the cil extractor option. 2024-03-12 11:12:56 +01:00
Michael Nebel
f59aaf1d75 C#: Add change note. 2024-03-12 11:12:55 +01:00
Michael Nebel
2e5155d1f8 C#: Remove all CIL related tests. 2024-03-12 11:12:55 +01:00
Michael Nebel
af06202241 C#: Cleanup implementation. 2024-03-12 11:12:55 +01:00
Michael Nebel
bf27f203d5 C#: Remove CIL extractor projects. 2024-03-12 11:12:55 +01:00
Tamas Vajk
1633673cc2 C#: Deduplicate not yet restored package names 2024-03-12 09:22:38 +01:00
Angela P Wen
ca12348ecb Merge pull request #15880 from github/sitedocs/2.16.4-2
Add changelog for 2.16.4
2024-03-11 14:59:53 -07:00
Pierre
d1f8336be6 Add changelog for 2.16.4 2024-03-11 22:21:25 +01:00
Ed Minnix
7745c2c2b7 Change note 2024-03-11 17:00:12 -04:00
Tom Hvitved
8d767862dc Swift: Implement new data flow interface 2024-03-11 20:56:38 +01:00
Tom Hvitved
1c57e99686 C++: Implement new data flow interface 2024-03-11 20:56:38 +01:00
Tom Hvitved
257686eb9a C#: Implement new data flow interface 2024-03-11 20:56:38 +01:00
Tom Hvitved
4291290277 Ruby: Implement new data flow interface 2024-03-11 20:56:38 +01:00
Tom Hvitved
e82e3180f0 Data flow: Replace hasLocationInfo with getLocation 2024-03-11 20:56:38 +01:00
Mathias Vorreiter Pedersen
9854ed4b89 C++: Delete comment. 2024-03-11 18:54:53 +00:00
Mathias Vorreiter Pedersen
2345907a52 C++: Reintroduce the 'cannotContainString' optimization that was removed in #15516. 2024-03-11 18:49:03 +00:00
Mathias Vorreiter Pedersen
f97b6e2848 C++: Stop conflating pointers and indirections in the query. 2024-03-11 18:48:19 +00:00
Mathias Vorreiter Pedersen
32e532ff3c C++: Some cleanup to avoid conflating the case of a function returning something as a return value, and a function updating one of its arguments. 2024-03-11 18:42:42 +00:00
Ed Minnix
bc745dfd5e Windows registry sources 2024-03-11 13:55:34 -04:00
erik-krogh
9f410eb2d6 Merge branch 'main' into ts-54 2024-03-11 18:07:52 +01:00
Joe Farebrother
9c51514bd9 Merge pull request #15857 from joefarebrother/ruby-activerecord-from
Ruby: Model second argument of `ActiveRecord` `from`
2024-03-11 16:49:52 +00:00
Henry Mercer
c325ff8a23 Mark lines of code queries as telemetry queries
The new file coverage metrics are available in all supported GHES
versions. This PR tags lines of code queries as telemetry queries. Lines
of code information will still be available in the SARIF file, but it
will no longer be displayed in the logging output of the CLI.

The one exception is the metric queries for Java/Kotlin that provides
separate lines of code information for Java and Kotlin. I've kept these
since separate file coverage information for languages like Java and
Kotlin is only available for GHES 3.12 and later.
2024-03-11 16:40:31 +00:00
Rasmus Lerchedahl Petersen
d73f43477f update ts to released version 54 2024-03-11 16:32:19 +01:00
Tony Torralba
04436208ab Merge pull request #15843 from atorralba/atorralba/go/uncontrolled-allocation-size
Go: Promote `go/uncontrolled-allocation-size` from experimental
2024-03-11 16:12:27 +01:00
Michael Nebel
5749fdbc46 Merge pull request #15868 from michaelnebel/csharp/csharp12releasenote
C#: Overall change note for C# 12 / .NET 8 support.
2024-03-11 16:08:24 +01:00
Tony Torralba
ff2d78d2c8 Update go/ql/src/Security/CWE-770/UncontrolledAllocationSize.ql 2024-03-11 15:53:40 +01:00
Ed Minnix
76aeee2820 Change note 2024-03-11 10:34:15 -04:00
Ed Minnix
61dbe26858 Add sinks for android.os.ParcelFileDescriptor 2024-03-11 10:31:51 -04:00
Mathias Vorreiter Pedersen
7b0df57d7a C++: Remove the two configurations that depend on flow state to speed up performance on ChakraCore. 2024-03-11 13:56:22 +00:00
Michael Nebel
f571ebdaf4 C#: Overall change note for C# 12 / .NET 8 support. 2024-03-11 14:43:14 +01:00
Rasmus Wriedt Larsen
800351c7b7 Merge branch 'main' into tt-consistency 2024-03-11 14:12:09 +01:00
yoff
e6e6a4e9c8 Merge pull request #15841 from RasmusWL/missing-use-use2
Python: Add example of missing use-use flow
2024-03-11 13:59:57 +01:00
yoff
adbcbefaa9 Merge pull request #15551 from yoff/python/avoid-duplicate-model-inclusions
python: Remove `TaintStepFromSummary`
2024-03-11 13:52:20 +01:00
Tom Hvitved
da66281fef Sync files 2024-03-11 13:02:04 +01:00
Tom Hvitved
7a39f077d9 Data flow: Add ConfigSig::accessPathLimit 2024-03-11 13:01:58 +01:00
Rasmus Wriedt Larsen
4ac8dd72a7 Merge pull request #15855 from yoff/python/add-MaD-test-tuple-output
Python: Add test for `ReturnValue.TupleElement[n]`
2024-03-11 12:05:31 +01:00
Mathias Vorreiter Pedersen
73c4fe08fa Merge pull request #15835 from MathiasVP/initial-def-of-addresses
C++: Provide an initial SSA definition of the address of a variable
2024-03-11 10:42:01 +00:00
Erik Krogh Kristensen
00c228540e Merge pull request #15836 from github/dependabot/cargo/ql/chrono-0.4.35
Bump chrono from 0.4.34 to 0.4.35 in /ql
2024-03-11 11:13:15 +01:00
Tony Torralba
a09eb9f4c5 Update go/ql/src/Security/CWE-770/UncontrolledAllocationSize.ql
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-03-11 08:58:59 +01:00
Joe Farebrother
dbd33d1cf0 Model Argument[1] of ActiveRecord from 2024-03-08 14:04:01 +00:00
Rasmus Lerchedahl Petersen
3601773856 python: support encoding lower bound 2024-03-08 14:59:28 +01:00
Rasmus Wriedt Larsen
adf5a4b1e4 Python: Fix internal consistency failures 2024-03-08 14:13:47 +01:00
Rasmus Wriedt Larsen
87b6592dbc Python: Accept inconsistency for missing use-use flow
At least until we have a proper fix
2024-03-08 13:34:26 +01:00
Rasmus Wriedt Larsen
8fe483d9d8 Python: Add example of missing use-use flow
(see PR for more detailed description)
2024-03-08 13:26:01 +01:00
Rasmus Lerchedahl Petersen
6d8d106d91 Python: add test for ReturnValue.TupleElement[n] 2024-03-08 11:18:51 +01:00
Tom Hvitved
24e35f6f3d Update expected test output 2024-03-08 10:00:43 +01:00
Tom Hvitved
63bb772ef9 Variable capture: Avoid overlapping and false-positive data flow paths 2024-03-08 10:00:42 +01:00
Tom Hvitved
e793a1e9fe Ruby: Add variable capture spurious flow test 2024-03-08 10:00:42 +01:00
Mathias Vorreiter Pedersen
761f6d3a7e C++: Disable field flow from the 'cpp/type-confusion' query to fix performance on ChakraCore. 2024-03-07 15:24:04 -08:00
Mathias Vorreiter Pedersen
a548316747 C++: Accept test changes. 2024-03-07 13:55:31 -08:00
Mathias Vorreiter Pedersen
4f9bdca4f0 C++: Optimize. 2024-03-07 13:08:26 -08:00
Mathias Vorreiter Pedersen
cedbfbe7ea C++: Use a more generous definition of compatible types. 2024-03-07 10:50:20 -08:00
Mathias Vorreiter Pedersen
9e77b89885 Update TypeConfusion.qhelp
Co-authored-by: hubwriter <hubwriter@github.com>
2024-03-07 08:33:49 -08:00
Tony Torralba
138ce42cf6 Fix qhelp 2024-03-07 15:22:46 +01:00
Tony Torralba
7d74125508 Go: Promote go/uncontrolled-allocation-size 2024-03-07 15:17:49 +01:00
Rasmus Wriedt Larsen
4dd8f6e618 Python: Add example of missing use-use flow
(see PR for more detailed description)
2024-03-07 14:25:55 +01:00
Mathias Vorreiter Pedersen
b876117ecc C++: Add more QLDoc. 2024-03-06 22:25:04 -08:00
Mathias Vorreiter Pedersen
01fc7432cb C++: Add more tests. 2024-03-06 22:17:33 -08:00
Mathias Vorreiter Pedersen
bf84f3a936 C++: Add FN. 2024-03-06 21:19:17 -08:00
Mathias Vorreiter Pedersen
3295d5cb9f C++: Add more QLDoc. 2024-03-06 21:17:57 -08:00
Mathias Vorreiter Pedersen
fc9919a5b6 C++: Add a test that exercise the 'last field' check. 2024-03-06 21:17:55 -08:00
Mathias Vorreiter Pedersen
c2db5f490e C++: Add more FNs and FPs to show examples of where the 'successor typing' strategy fails. 2024-03-06 21:16:51 -08:00
Mathias Vorreiter Pedersen
cd57cd0d8a C++: Add qhelp reference. 2024-03-06 21:15:27 -08:00
Mathias Vorreiter Pedersen
cf4c8eb517 C++: Add more tests. 2024-03-06 21:15:25 -08:00
Mathias Vorreiter Pedersen
6dc0fa515d C++: Add change note. 2024-03-06 21:11:36 -08:00
Mathias Vorreiter Pedersen
8ae6fa5366 C++: Add a new query 'cpp/type-confusion' for detecting type confusion vulnerabilities. 2024-03-06 21:11:32 -08:00
dependabot[bot]
f0a5183a3f Bump chrono from 0.4.34 to 0.4.35 in /ql
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.34 to 0.4.35.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.34...v0.4.35)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-07 03:59:07 +00:00
Angela P Wen
31f1f50a64 Merge pull request #15834 from github/post-release-prep/codeql-cli-2.16.4
Post-release preparation for codeql-cli-2.16.4
2024-03-06 18:40:08 -08:00
Mathias Vorreiter Pedersen
4c9876b008 C++: Accept test changes. 2024-03-06 18:18:36 -08:00
Mathias Vorreiter Pedersen
cf162aa412 C++: Add an explicit definition of the address of an IRVariable. 2024-03-06 18:18:33 -08:00
Mathias Vorreiter Pedersen
84797b9091 C++: Refactor the address out of 'DefImpl' and into a new abstract class 'OperandBasedDef'. 2024-03-06 18:15:52 -08:00
Mathias Vorreiter Pedersen
cc754858c6 C++: Add a testcase with missing flow out of the address of 'a' and to the argument of 'sink'. 2024-03-06 18:15:49 -08:00
Mathias Vorreiter Pedersen
a60afef923 C++: Add a local flow test file for IR dataflow. 2024-03-06 18:10:08 -08:00
github-actions[bot]
dc9092c9ec Post-release preparation for codeql-cli-2.16.4 2024-03-06 22:19:33 +00:00
Angela P Wen
2daf50500c Merge pull request #15833 from github/release-prep/2.16.4
Release preparation for version 2.16.4
2024-03-06 13:00:06 -08:00
github-actions[bot]
2f058ffb4d Release preparation for version 2.16.4 2024-03-06 20:56:51 +00:00
Angela P Wen
711c474049 Merge pull request #15832 from github/revert-15814-release-prep/2.16.4
Revert "Release preparation for version 2.16.4"
2024-03-06 12:53:52 -08:00
Angela P Wen
ce31f8641a Revert "Release preparation for version 2.16.4" 2024-03-06 12:07:33 -08:00
Angela P Wen
727a38a409 Merge pull request #15814 from github/release-prep/2.16.4
Release preparation for version 2.16.4
2024-03-05 10:16:21 -08:00
github-actions[bot]
661e68dab5 Release preparation for version 2.16.4 2024-03-05 18:13:58 +00:00
Angela P Wen
7e2a775a2a Merge pull request #15813 from github/revert-15801-release-prep/2.16.4
Revert "Release preparation for version 2.16.4"
2024-03-05 09:20:42 -08:00
Angela P Wen
967963a653 Revert "Release preparation for version 2.16.4" 2024-03-05 08:53:33 -08:00
Michael B. Gale
eaef544a26 Merge pull request #15810 from github/mbg/go/fix-initialised-module-names 2024-03-05 15:34:07 +00:00
Michael B. Gale
40ff75db07 Go: Update list of expected files for single-go-mod-and-go-files-not-under-it test 2024-03-05 14:56:51 +00:00
Michael B. Gale
a8d240dd72 Go: Add integration test for mixed layout project 2024-03-05 14:08:16 +00:00
Michael B. Gale
ac394dc80c Go: Better check for path prefixes 2024-03-05 13:46:33 +00:00
Michael B. Gale
b1e0bc03ab Go: Fix check for whether it is safe to initialise a go.mod file in a given directory 2024-03-05 12:48:21 +00:00
Michael B. Gale
367ecf75d5 Go: Use import path for auto-generated Go module names 2024-03-05 12:48:21 +00:00
Michael B. Gale
2aa093c95c Go: Move getImportPath to shared util package 2024-03-05 12:48:19 +00:00
Harry Maclean
148241183a Ruby: update changenote 2024-03-05 10:20:25 +00:00
Harry Maclean
91cb2a37fd Ruby: Model Process.exec 2024-03-05 10:19:22 +00:00
Harry Maclean
179aaa1342 Ruby: model Open4.popen4ext 2024-03-05 09:35:18 +00:00
Angela P Wen
92e91f596f Merge pull request #15801 from github/release-prep/2.16.4
Release preparation for version 2.16.4
2024-03-04 10:57:55 -08:00
github-actions[bot]
a67218a027 Release preparation for version 2.16.4 2024-03-04 17:42:08 +00:00
Angela P Wen
19539ab6d8 Merge pull request #15800 from github/angelapwen/fix-ruby-changenotes
Fix Markdown formatting on Ruby changenotes
2024-03-04 08:52:13 -08:00
Angela P Wen
2b2ea597ce Fix formatting on changenotes 2024-03-04 16:42:38 +00:00
Rasmus Wriedt Larsen
7c60562132 Python: Ignore IterableSequenceNode inconsistencies 2024-03-01 14:22:18 +01:00
Rasmus Wriedt Larsen
7e3e5db3db Python: Add example of consistency failure 2024-03-01 14:21:16 +01:00
Rasmus Wriedt Larsen
bcd5c08ebd Python: Ignore match-related inconsistencies 2024-03-01 14:15:32 +01:00
Rasmus Wriedt Larsen
5d212514c6 Python: Add example of consistency failure 2024-03-01 14:07:08 +01:00
Rasmus Wriedt Larsen
1658a1cb80 Python: Ignore SynthDictSplatArgumentNode failures 2024-03-01 14:00:06 +01:00
Rasmus Wriedt Larsen
bff95c4c1b Python: Add example of consistency failure 2024-03-01 13:58:33 +01:00
Rasmus Wriedt Larsen
ff5f794750 Python: Exclude synth preupdate nodes from tt-consistency
... and that should be it 👍 (so that's why I'm allowing the tests to
run on all data-flow nodes again)
2024-03-01 10:27:29 +01:00
Rasmus Wriedt Larsen
bbe8c6dcaa Python: Remove synth postupdate nodes from tt-consistency 2024-03-01 10:23:50 +01:00
Rasmus Wriedt Larsen
9f01ea68f7 Python: Add type-tracking consistency query
For now I'm only ignoring stdlib nodes, so it's easy for reviewer to see
why we need to have more excludes :)
2024-03-01 10:19:49 +01:00
Asger F
853397361f JS: Do not treat AMD pseudo-dependencies as file paths 2024-02-29 10:23:28 +01:00
Asger F
052a8e7f81 JS: Avoid spurious recursion in AMD 2024-02-29 10:23:28 +01:00
Harry Maclean
d0e7fbc871 Ruby: Add changenote 2024-02-27 09:47:51 +00:00
erik-krogh
b4b5ae2a2c add some request-forgery sanitizers, inspired from C# 2024-02-27 10:05:26 +01:00
Rasmus Lerchedahl Petersen
3eb9491cb4 python: rewrite HardcodedCredentials away from PointsTo
- `ModuleValue.attr` and `ClassValue.lookup` are approximated by `Function.getName`
- `ClassValue.getName` is apprximated by `Class.getName`
- `Module::named` is approximated by `Module.getName`
- `Value::named` is approximated by `Builtins::likelyBuiltin`
- `FunctionValue.getNamedArgumentForCall` is approximated by `ArgumentNode.argumentOf`
2024-02-26 17:18:40 +01:00
Harry Maclean
8bed3fbed4 Ruby: Add basic model for Terrapin library 2024-02-26 11:32:41 +00:00
Harry Maclean
9d13a1ff51 Ruby: Add model for Process.spawn 2024-02-26 11:26:38 +00:00
Harry Maclean
d1847566b6 Ruby: Ql4QL fix 2024-02-26 11:26:38 +00:00
Harry Maclean
beef9965cc Ruby: Model Open4 library
Also remove duplicate modeling of Process.spawn.
2024-02-26 11:26:38 +00:00
Harry Maclean
a03c06802e Ruby: Add some more command injection sinks 2024-02-26 11:26:38 +00:00
erik-krogh
0056067a17 Merge branch 'main' into ts-54 2024-02-25 21:20:43 +01:00
erik-krogh
083f56921c update to 5.4.1-rc 2024-02-25 21:20:41 +01:00
Rasmus Lerchedahl Petersen
580e68d5de python: add support for lower bound position 2024-02-09 13:51:16 +01:00
Rasmus Lerchedahl Petersen
45bb4a0ee5 python: remove TaintStepFromSummary
as it should be covered by `SummarizedCallableFromModel`

Also move things around, to look more like the Ruby code.
2024-02-08 12:48:15 +01:00
Rasmus Lerchedahl Petersen
3b1751dc8a Update supported versions 2024-02-02 11:45:21 +01:00
Rasmus Lerchedahl Petersen
f433039a25 Add change note 2024-02-02 11:23:35 +01:00
Rasmus Lerchedahl Petersen
f275531542 Add support for TS 5.4-beta 2024-02-02 11:03:44 +01:00
1306 changed files with 96991 additions and 72162 deletions

View File

@@ -1 +1 @@
7.0.2
7.1.0

View File

@@ -0,0 +1,55 @@
name: "Code scanning - C++"
on:
push:
branches:
- main
- 'rc/*'
pull_request:
branches:
- main
- 'rc/*'
paths:
- 'swift/**'
- '.github/codeql/**'
- '.github/workflows/cpp-swift-analysis.yml'
schedule:
- cron: '0 9 * * 1'
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
pull-requests: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@main
# Override language selection by uncommenting this and choosing your languages
with:
languages: cpp
config-file: ./.github/codeql/codeql-config.yml
- name: "[Ubuntu] Remove GCC 13 from runner image"
shell: bash
run: |
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list
sudo apt-get update
sudo apt-get install -y --allow-downgrades libc6=2.35-* libc6-dev=2.35-* libstdc++6=12.3.0-* libgcc-s1=12.3.0-*
- name: "Build Swift extractor using Bazel"
run: |
bazel clean --expunge
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
bazel shutdown
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@main

View File

@@ -1,4 +1,5 @@
/cpp/ @github/codeql-c-analysis
/cpp/autobuilder/ @github/codeql-c-extractor
/csharp/ @github/codeql-csharp
/go/ @github/codeql-go
/java/ @github/codeql-java

View File

@@ -6,6 +6,7 @@ provide:
- "*/ql/consistency-queries/qlpack.yml"
- "*/ql/automodel/src/qlpack.yml"
- "*/ql/automodel/test/qlpack.yml"
- "python/extractor/qlpack.yml"
- "shared/**/qlpack.yml"
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
- "go/ql/config/legacy-support/qlpack.yml"
@@ -27,7 +28,6 @@ provide:
- "misc/suite-helpers/qlpack.yml"
- "ruby/extractor-pack/codeql-extractor.yml"
- "swift/extractor-pack/codeql-extractor.yml"
- "swift/integration-tests/qlpack.yml"
- "ql/extractor-pack/codeql-extractor.yml"
- ".github/codeql/extensions/**/codeql-pack.yml"

View File

@@ -255,7 +255,6 @@
"cpp/ql/lib/semmle/code/cpp/XML.qll",
"csharp/ql/lib/semmle/code/csharp/XML.qll",
"java/ql/lib/semmle/code/xml/XML.qll",
"javascript/ql/lib/semmle/javascript/XML.qll",
"python/ql/lib/semmle/python/xml/XML.qll"
],
"DuplicationProblems.inc.qhelp": [
@@ -372,4 +371,4 @@
"python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml"
]
}
}

View File

@@ -0,0 +1,13 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
from Expr expr, int kind, int kind_new, Location loc
where
exprs(expr, kind, loc) and
if kind = 363 then kind_new = 1 else kind_new = kind
select expr, kind_new, loc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Introduce re-use expressions
compatibility: partial
expr_reuse.rel: delete
exprs.rel: run exprs.qlo

View File

@@ -0,0 +1,7 @@
class Expr extends @expr {
string toString() { none() }
}
from Expr reuse, Expr original
where expr_reuse(reuse, original, _)
select reuse, original

View File

@@ -0,0 +1,22 @@
class Expr extends @expr {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
predicate existingType(Expr expr, Type type, int value_category) {
expr_types(expr, type, value_category)
}
predicate reuseType(Expr reuse, Type type, int value_category) {
exists(Expr original |
expr_reuse(reuse, original, value_category) and
expr_types(original, type, _)
)
}
from Expr expr, Type type, int value_category
where existingType(expr, type, value_category) or reuseType(expr, type, value_category)
select expr, type, value_category

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Add value category to expr_reuse table
compatibility: full
expr_reuse.rel: run expr_reuse.qlo
expr_types.rel: run expr_types.qlo

View File

@@ -1,3 +1,32 @@
## 0.12.10
### New Features
* Added a `TaintInheritingContent` class that can be extended to model taint flowing from a qualifier to a field.
* Added a predicate `GuardCondition.comparesEq/4` to query whether an expression is compared to a constant.
* Added a predicate `GuardCondition.ensuresEq/4` to query whether a basic block is guarded by an expression being equal to a constant.
* Added a predicate `GuardCondition.comparesLt/4` to query whether an expression is compared to a constant.
* Added a predicate `GuardCondition.ensuresLt/4` to query whether a basic block is guarded by an expression being less than a constant.
* Added a predicate `GuardCondition.valueControls` to query whether a basic block is guarded by a particular `case` of a `switch` statement.
### Minor Analysis Improvements
* Added destructors for temporary objects with extended lifetimes to the intermediate representation.
## 0.12.9
No user-facing changes.
## 0.12.8
No user-facing changes.
## 0.12.7
### Minor Analysis Improvements
* Added destructors for named objects to the intermediate representation.
## 0.12.6
### New Features

View File

@@ -0,0 +1,14 @@
## 0.12.10
### New Features
* Added a `TaintInheritingContent` class that can be extended to model taint flowing from a qualifier to a field.
* Added a predicate `GuardCondition.comparesEq/4` to query whether an expression is compared to a constant.
* Added a predicate `GuardCondition.ensuresEq/4` to query whether a basic block is guarded by an expression being equal to a constant.
* Added a predicate `GuardCondition.comparesLt/4` to query whether an expression is compared to a constant.
* Added a predicate `GuardCondition.ensuresLt/4` to query whether a basic block is guarded by an expression being less than a constant.
* Added a predicate `GuardCondition.valueControls` to query whether a basic block is guarded by a particular `case` of a `switch` statement.
### Minor Analysis Improvements
* Added destructors for temporary objects with extended lifetimes to the intermediate representation.

View File

@@ -1,4 +1,5 @@
---
category: minorAnalysis
---
* Added destructors for named objects to the intermediate representation.
## 0.12.7
### Minor Analysis Improvements
* Added destructors for named objects to the intermediate representation.

View File

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

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.12.6
lastReleaseVersion: 0.12.10

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.12.7-dev
version: 0.12.10
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -309,9 +309,12 @@ class ExprNode extends AstNode {
override AstNode getChildInternal(int childIndex) {
result.getAst() = expr.getChild(childIndex)
or
childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and
result.getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
or
exists(int destructorIndex |
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 1
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2
)
}
@@ -686,6 +689,8 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
not namedExprChildPredicates(expr, child, _) and
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
or
expr.(ConditionDeclExpr).getInitializingExpr() = child and result = "getInitializingExpr()"
or
exists(int n |
expr.getImplicitDestructorCall(n) = child and
result = "getImplicitDestructorCall(" + n + ")"

View File

@@ -590,6 +590,33 @@ class TemplateVariable extends Variable {
Variable getAnInstantiation() { result.isConstructedFrom(this) }
}
/**
* A variable that is an instantiation of a template. For example
* the instantiation `myTemplateVariable<int>` in the following code:
* ```
* template<class T>
* T myTemplateVariable;
*
* void caller(int i) {
* myTemplateVariable<int> = i;
* }
* ```
*/
class VariableTemplateInstantiation extends Variable {
TemplateVariable tv;
VariableTemplateInstantiation() { tv.getAnInstantiation() = this }
override string getAPrimaryQlClass() { result = "VariableTemplateInstantiation" }
/**
* Gets the variable template from which this instantiation was instantiated.
*
* Example: For `int x<int>`, returns `T x`.
*/
TemplateVariable getTemplate() { result = tv }
}
/**
* A non-static local variable or parameter that is not part of an
* uninstantiated template. Uninstantiated templates are purely syntax, and

View File

@@ -20,6 +20,44 @@ private predicate isUnreachedBlock(IRBlock block) {
block.getFirstInstruction() instanceof UnreachedInstruction
}
private newtype TAbstractValue =
TBooleanValue(boolean b) { b = true or b = false } or
TMatchValue(CaseEdge c)
/**
* An abstract value. This is either a boolean value, or a `switch` case.
*/
abstract class AbstractValue extends TAbstractValue {
/** Gets an abstract value that represents the dual of this value, if any. */
abstract AbstractValue getDualValue();
/** Gets a textual representation of this abstract value. */
abstract string toString();
}
/** A Boolean value. */
class BooleanValue extends AbstractValue, TBooleanValue {
/** Gets the underlying Boolean value. */
boolean getValue() { this = TBooleanValue(result) }
override BooleanValue getDualValue() { result.getValue() = this.getValue().booleanNot() }
override string toString() { result = this.getValue().toString() }
}
/** A value that represents a match against a specific `switch` case. */
class MatchValue extends AbstractValue, TMatchValue {
/** Gets the case. */
CaseEdge getCase() { this = TMatchValue(result) }
override MatchValue getDualValue() {
// A `MatchValue` has no dual.
none()
}
override string toString() { result = this.getCase().toString() }
}
/**
* A Boolean condition in the AST that guards one or more basic blocks. This includes
* operands of logical operators but not switch statements.
@@ -34,6 +72,15 @@ class GuardCondition extends Expr {
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
}
/**
* Holds if this condition controls `controlled`, meaning that `controlled` is only
* entered if the value of this condition is `v`.
*
* For details on what "controls" mean, see the QLDoc for `controls`.
*/
cached
predicate valueControls(BasicBlock controlled, AbstractValue v) { none() }
/**
* Holds if this condition controls `controlled`, meaning that `controlled` is only
* entered if the value of this condition is `testIsTrue`.
@@ -61,7 +108,9 @@ class GuardCondition extends Expr {
* true (for `&&`) or false (for `||`) branch.
*/
cached
predicate controls(BasicBlock controlled, boolean testIsTrue) { none() }
final predicate controls(BasicBlock controlled, boolean testIsTrue) {
this.valueControls(controlled, any(BooleanValue bv | bv.getValue() = testIsTrue))
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
cached
@@ -76,6 +125,20 @@ class GuardCondition extends Expr {
cached
predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { none() }
/**
* Holds if (determined by this guard) `e < k` evaluates to `isLessThan` if
* this expression evaluates to `value`.
*/
cached
predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) { none() }
/**
* Holds if (determined by this guard) `e < k` must be `isLessThan` in `block`.
* If `isLessThan = false` then this implies `e >= k`.
*/
cached
predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) { none() }
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
cached
predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
@@ -88,6 +151,17 @@ class GuardCondition extends Expr {
*/
cached
predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { none() }
/** Holds if (determined by this guard) `e == k` evaluates to `areEqual` if this expression evaluates to `value`. */
cached
predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) { none() }
/**
* Holds if (determined by this guard) `e == k` must be `areEqual` in `block`.
* If `areEqual = false` then this implies `e != k`.
*/
cached
predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) { none() }
}
/**
@@ -98,13 +172,13 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
}
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
this = binop and
lhs = binop.getLeftOperand() and
rhs = binop.getRightOperand() and
lhs.controls(controlled, testIsTrue) and
rhs.controls(controlled, testIsTrue)
lhs.valueControls(controlled, v) and
rhs.valueControls(controlled, v)
)
}
@@ -116,12 +190,27 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
)
}
override predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) {
exists(BooleanValue partValue, GuardCondition part |
this.(BinaryLogicalOperation)
.impliesValue(part, partValue.getValue(), value.(BooleanValue).getValue())
|
part.comparesLt(e, k, isLessThan, partValue)
)
}
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
)
}
override predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) {
exists(AbstractValue value |
this.comparesLt(e, k, isLessThan, value) and this.valueControls(block, value)
)
}
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
exists(boolean partIsTrue, GuardCondition part |
this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue)
@@ -135,6 +224,21 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
)
}
override predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) {
exists(BooleanValue partValue, GuardCondition part |
this.(BinaryLogicalOperation)
.impliesValue(part, partValue.getValue(), value.(BooleanValue).getValue())
|
part.comparesEq(e, k, areEqual, partValue)
)
}
override predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) {
exists(AbstractValue value |
this.comparesEq(e, k, areEqual, value) and this.valueControls(block, value)
)
}
}
/**
@@ -146,13 +250,12 @@ private class GuardConditionFromIR extends GuardCondition {
GuardConditionFromIR() { this = ir.getUnconvertedResultExpression() }
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
// This condition must determine the flow of control; that is, this
// node must be a top-level condition.
this.controlsBlock(controlled, testIsTrue)
this.controlsBlock(controlled, v)
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
exists(Instruction li, Instruction ri |
li.getUnconvertedResultExpression() = left and
@@ -161,10 +264,13 @@ private class GuardConditionFromIR extends GuardCondition {
)
}
/**
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
* If `isLessThan = false` then this implies `left >= right + k`.
*/
override predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) {
exists(Instruction i |
i.getUnconvertedResultExpression() = e and
ir.comparesLt(i.getAUse(), k, isLessThan, value)
)
}
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(Instruction li, Instruction ri, boolean testIsTrue |
li.getUnconvertedResultExpression() = left and
@@ -174,7 +280,14 @@ private class GuardConditionFromIR extends GuardCondition {
)
}
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
override predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) {
exists(Instruction i, AbstractValue value |
i.getUnconvertedResultExpression() = e and
ir.comparesLt(i.getAUse(), k, isLessThan, value) and
this.valueControls(block, value)
)
}
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
exists(Instruction li, Instruction ri |
li.getUnconvertedResultExpression() = left and
@@ -183,10 +296,6 @@ private class GuardConditionFromIR extends GuardCondition {
)
}
/**
* Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
* If `areEqual = false` then this implies `left != right + k`.
*/
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
exists(Instruction li, Instruction ri, boolean testIsTrue |
li.getUnconvertedResultExpression() = left and
@@ -196,15 +305,30 @@ private class GuardConditionFromIR extends GuardCondition {
)
}
override predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) {
exists(Instruction i |
i.getUnconvertedResultExpression() = e and
ir.comparesEq(i.getAUse(), k, areEqual, value)
)
}
override predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) {
exists(Instruction i, AbstractValue value |
i.getUnconvertedResultExpression() = e and
ir.comparesEq(i.getAUse(), k, areEqual, value) and
this.valueControls(block, value)
)
}
/**
* Holds if this condition controls `block`, meaning that `block` is only
* entered if the value of this condition is `testIsTrue`. This helper
* entered if the value of this condition is `v`. This helper
* predicate does not necessarily hold for binary logical operations like
* `&&` and `||`. See the detailed explanation on predicate `controls`.
*/
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
private predicate controlsBlock(BasicBlock controlled, AbstractValue v) {
exists(IRBlock irb |
ir.controls(irb, testIsTrue) and
ir.valueControls(irb, v) and
nonExcludedIRAndBasicBlock(irb, controlled) and
not isUnreachedBlock(irb)
)
@@ -249,10 +373,28 @@ private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled)
*/
cached
class IRGuardCondition extends Instruction {
ConditionalBranchInstruction branch;
Instruction branch;
cached
IRGuardCondition() { branch = get_branch_for_condition(this) }
IRGuardCondition() { branch = getBranchForCondition(this) }
/**
* Holds if this condition controls `controlled`, meaning that `controlled` is only
* entered if the value of this condition is `v`.
*
* For details on what "controls" mean, see the QLDoc for `controls`.
*/
cached
predicate valueControls(IRBlock controlled, AbstractValue v) {
// This condition must determine the flow of control; that is, this
// node must be a top-level condition.
this.controlsBlock(controlled, v)
or
exists(IRGuardCondition ne |
this = ne.(LogicalNotInstruction).getUnary() and
ne.valueControls(controlled, v.getDualValue())
)
}
/**
* Holds if this condition controls `controlled`, meaning that `controlled` is only
@@ -282,13 +424,25 @@ class IRGuardCondition extends Instruction {
*/
cached
predicate controls(IRBlock controlled, boolean testIsTrue) {
// This condition must determine the flow of control; that is, this
// node must be a top-level condition.
this.controlsBlock(controlled, testIsTrue)
this.valueControls(controlled, any(BooleanValue bv | bv.getValue() = testIsTrue))
}
/**
* Holds if the control-flow edge `(pred, succ)` may be taken only if
* the value of this condition is `v`.
*/
cached
predicate valueControlsEdge(IRBlock pred, IRBlock succ, AbstractValue v) {
pred.getASuccessor() = succ and
this.valueControls(pred, v)
or
exists(IRGuardCondition ne |
this = ne.(LogicalNotInstruction).getUnary() and
ne.controls(controlled, testIsTrue.booleanNot())
succ = this.getBranchSuccessor(v) and
(
branch.(ConditionalBranchInstruction).getCondition() = this and
branch.getBlock() = pred
or
branch.(SwitchInstruction).getExpression() = this and
branch.getBlock() = pred
)
}
@@ -297,17 +451,12 @@ class IRGuardCondition extends Instruction {
* the value of this condition is `testIsTrue`.
*/
cached
predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
pred.getASuccessor() = succ and
this.controls(pred, testIsTrue)
or
succ = this.getBranchSuccessor(testIsTrue) and
branch.getCondition() = this and
branch.getBlock() = pred
final predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
this.valueControlsEdge(pred, succ, any(BooleanValue bv | bv.getValue() = testIsTrue))
}
/**
* Gets the block to which `branch` jumps directly when this condition is `testIsTrue`.
* Gets the block to which `branch` jumps directly when the value of this condition is `v`.
*
* This predicate is intended to help with situations in which an inference can only be made
* based on an edge between a block with multiple successors and a block with multiple
@@ -321,21 +470,39 @@ class IRGuardCondition extends Instruction {
* return x;
* ```
*/
private IRBlock getBranchSuccessor(boolean testIsTrue) {
branch.getCondition() = this and
(
testIsTrue = true and
result.getFirstInstruction() = branch.getTrueSuccessor()
private IRBlock getBranchSuccessor(AbstractValue v) {
branch.(ConditionalBranchInstruction).getCondition() = this and
exists(BooleanValue bv | bv = v |
bv.getValue() = true and
result.getFirstInstruction() = branch.(ConditionalBranchInstruction).getTrueSuccessor()
or
testIsTrue = false and
result.getFirstInstruction() = branch.getFalseSuccessor()
bv.getValue() = false and
result.getFirstInstruction() = branch.(ConditionalBranchInstruction).getFalseSuccessor()
)
or
exists(SwitchInstruction switch, CaseEdge kind | switch = branch |
switch.getExpression() = this and
result.getFirstInstruction() = switch.getSuccessor(kind) and
kind = v.(MatchValue).getCase()
)
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
cached
predicate comparesLt(Operand left, Operand right, int k, boolean isLessThan, boolean testIsTrue) {
compares_lt(this, left, right, k, isLessThan, testIsTrue)
exists(BooleanValue value |
compares_lt(this, left, right, k, isLessThan, value) and
value.getValue() = testIsTrue
)
}
/**
* Holds if (determined by this guard) `op < k` evaluates to `isLessThan` if
* this expression evaluates to `value`.
*/
cached
predicate comparesLt(Operand op, int k, boolean isLessThan, AbstractValue value) {
compares_lt(this, op, k, isLessThan, value)
}
/**
@@ -344,8 +511,19 @@ class IRGuardCondition extends Instruction {
*/
cached
predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
exists(AbstractValue value |
compares_lt(this, left, right, k, isLessThan, value) and this.valueControls(block, value)
)
}
/**
* Holds if (determined by this guard) `op < k` must be `isLessThan` in `block`.
* If `isLessThan = false` then this implies `op >= k`.
*/
cached
predicate ensuresLt(Operand op, int k, IRBlock block, boolean isLessThan) {
exists(AbstractValue value |
compares_lt(this, op, k, isLessThan, value) and this.valueControls(block, value)
)
}
@@ -357,16 +535,37 @@ class IRGuardCondition extends Instruction {
predicate ensuresLtEdge(
Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean isLessThan
) {
exists(boolean testIsTrue |
compares_lt(this, left, right, k, isLessThan, testIsTrue) and
this.controlsEdge(pred, succ, testIsTrue)
exists(AbstractValue value |
compares_lt(this, left, right, k, isLessThan, value) and
this.valueControlsEdge(pred, succ, value)
)
}
/**
* Holds if (determined by this guard) `op < k` must be `isLessThan` on the edge from
* `pred` to `succ`. If `isLessThan = false` then this implies `op >= k`.
*/
cached
predicate ensuresLtEdge(Operand left, int k, IRBlock pred, IRBlock succ, boolean isLessThan) {
exists(AbstractValue value |
compares_lt(this, left, k, isLessThan, value) and
this.valueControlsEdge(pred, succ, value)
)
}
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
cached
predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
compares_eq(this, left, right, k, areEqual, testIsTrue)
exists(BooleanValue value |
compares_eq(this, left, right, k, areEqual, value) and
value.getValue() = testIsTrue
)
}
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `value`. */
cached
predicate comparesEq(Operand op, int k, boolean areEqual, AbstractValue value) {
compares_eq(this, op, k, areEqual, value)
}
/**
@@ -375,8 +574,19 @@ class IRGuardCondition extends Instruction {
*/
cached
predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
exists(boolean testIsTrue |
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
exists(AbstractValue value |
compares_eq(this, left, right, k, areEqual, value) and this.valueControls(block, value)
)
}
/**
* Holds if (determined by this guard) `op == k` must be `areEqual` in `block`.
* If `areEqual = false` then this implies `op != k`.
*/
cached
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
exists(AbstractValue value |
compares_eq(this, op, k, areEqual, value) and this.valueControls(block, value)
)
}
@@ -388,19 +598,31 @@ class IRGuardCondition extends Instruction {
predicate ensuresEqEdge(
Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean areEqual
) {
exists(boolean testIsTrue |
compares_eq(this, left, right, k, areEqual, testIsTrue) and
this.controlsEdge(pred, succ, testIsTrue)
exists(AbstractValue value |
compares_eq(this, left, right, k, areEqual, value) and
this.valueControlsEdge(pred, succ, value)
)
}
/**
* Holds if (determined by this guard) `op == k` must be `areEqual` on the edge from
* `pred` to `succ`. If `areEqual = false` then this implies `op != k`.
*/
cached
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
exists(AbstractValue value |
compares_eq(this, op, k, areEqual, value) and
this.valueControlsEdge(pred, succ, value)
)
}
/**
* Holds if this condition controls `block`, meaning that `block` is only
* entered if the value of this condition is `testIsTrue`. This helper
* entered if the value of this condition is `v`. This helper
* predicate does not necessarily hold for binary logical operations like
* `&&` and `||`. See the detailed explanation on predicate `controls`.
*/
private predicate controlsBlock(IRBlock controlled, boolean testIsTrue) {
private predicate controlsBlock(IRBlock controlled, AbstractValue v) {
not isUnreachedBlock(controlled) and
//
// For this block to control the block `controlled` with `testIsTrue` the
@@ -441,7 +663,7 @@ class IRGuardCondition extends Instruction {
// that `this` strictly dominates `controlled` so that isn't necessary to check
// directly.
exists(IRBlock succ |
succ = this.getBranchSuccessor(testIsTrue) and
succ = this.getBranchSuccessor(v) and
this.hasDominatingEdgeTo(succ) and
succ.dominates(controlled)
)
@@ -476,12 +698,14 @@ class IRGuardCondition extends Instruction {
private IRBlock getBranchBlock() { result = branch.getBlock() }
}
private ConditionalBranchInstruction get_branch_for_condition(Instruction guard) {
result.getCondition() = guard
private Instruction getBranchForCondition(Instruction guard) {
result.(ConditionalBranchInstruction).getCondition() = guard
or
exists(LogicalNotInstruction cond |
result = get_branch_for_condition(cond) and cond.getUnary() = guard
result = getBranchForCondition(cond) and cond.getUnary() = guard
)
or
result.(SwitchInstruction).getExpression() = guard
}
/**
@@ -490,52 +714,98 @@ private ConditionalBranchInstruction get_branch_for_condition(Instruction guard)
* Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`.
*/
private predicate compares_eq(
Instruction test, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
Instruction test, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) |
areEqual = true and testIsTrue = eq
exists(AbstractValue v | simple_comparison_eq(test, left, right, k, v) |
areEqual = true and value = v
or
areEqual = false and testIsTrue = eq.booleanNot()
areEqual = false and value = v.getDualValue()
)
or
// I think this is handled by forwarding in controlsBlock.
//or
//logical_comparison_eq(test, left, right, k, areEqual, testIsTrue)
/* a == b + k => b == a - k */
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue))
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, value))
or
complex_eq(test, left, right, k, areEqual, testIsTrue)
complex_eq(test, left, right, k, areEqual, value)
or
/* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, isFalse)
exists(AbstractValue dual | value = dual.getDualValue() |
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, dual)
)
}
/** Holds if `op == k` is `areEqual` given that `test` is equal to `value`. */
private predicate compares_eq(
Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
) {
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
exists(AbstractValue v | simple_comparison_eq(test, op, k, v) |
areEqual = true and value = v
or
areEqual = false and value = v.getDualValue()
)
or
complex_eq(test, op, k, areEqual, value)
or
/* (x is true => (op == k)) => (!x is false => (op == k)) */
exists(AbstractValue dual | value = dual.getDualValue() |
compares_eq(test.(LogicalNotInstruction).getUnary(), op, k, areEqual, dual)
)
or
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
// test is `areEqual` => op == k1 + k2
exists(int k1, int k2, ConstantInstruction const |
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
int_value(const) = k1 and
k = k1 + k2
)
}
/** Rearrange various simple comparisons into `left == right + k` form. */
private predicate simple_comparison_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual
CompareInstruction cmp, Operand left, Operand right, int k, AbstractValue value
) {
left = cmp.getLeftOperand() and
cmp instanceof CompareEQInstruction and
right = cmp.getRightOperand() and
k = 0 and
areEqual = true
value.(BooleanValue).getValue() = true
or
left = cmp.getLeftOperand() and
cmp instanceof CompareNEInstruction and
right = cmp.getRightOperand() and
k = 0 and
areEqual = false
value.(BooleanValue).getValue() = false
}
/** Rearrange various simple comparisons into `op == k` form. */
private predicate simple_comparison_eq(Instruction test, Operand op, int k, AbstractValue value) {
exists(SwitchInstruction switch, CaseEdge case |
test = switch.getExpression() and
op.getDef() = test and
case = value.(MatchValue).getCase() and
exists(switch.getSuccessor(case)) and
case.getValue().toInt() = k
)
}
private predicate complex_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
sub_eq(cmp, left, right, k, areEqual, testIsTrue)
sub_eq(cmp, left, right, k, areEqual, value)
or
add_eq(cmp, left, right, k, areEqual, testIsTrue)
add_eq(cmp, left, right, k, areEqual, value)
}
private predicate complex_eq(
Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
) {
sub_eq(test, op, k, areEqual, value)
or
add_eq(test, op, k, areEqual, value)
}
/*
@@ -545,31 +815,46 @@ private predicate complex_eq(
/** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */
private predicate compares_lt(
Instruction test, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
Instruction test, Operand left, Operand right, int k, boolean isLt, AbstractValue value
) {
/* In the simple case, the test is the comparison, so isLt = testIsTrue */
simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true
simple_comparison_lt(test, left, right, k) and
value.(BooleanValue).getValue() = isLt
or
simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false
or
complex_lt(test, left, right, k, isLt, testIsTrue)
complex_lt(test, left, right, k, isLt, value)
or
/* (not (left < right + k)) => (left >= right + k) */
exists(boolean isGe | isLt = isGe.booleanNot() |
compares_ge(test, left, right, k, isGe, testIsTrue)
)
exists(boolean isGe | isLt = isGe.booleanNot() | compares_ge(test, left, right, k, isGe, value))
or
/* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
compares_lt(test.(LogicalNotInstruction).getUnary(), left, right, k, isLt, isFalse)
exists(AbstractValue dual | value = dual.getDualValue() |
compares_lt(test.(LogicalNotInstruction).getUnary(), left, right, k, isLt, dual)
)
}
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
private predicate compares_lt(Instruction test, Operand op, int k, boolean isLt, AbstractValue value) {
simple_comparison_lt(test, op, k, isLt, value)
or
complex_lt(test, op, k, isLt, value)
or
/* (x is true => (op < k)) => (!x is false => (op < k)) */
exists(AbstractValue dual | value = dual.getDualValue() |
compares_lt(test.(LogicalNotInstruction).getUnary(), op, k, isLt, dual)
)
or
exists(int k1, int k2, ConstantInstruction const |
compares_lt(test, op, const.getAUse(), k2, isLt, value) and
int_value(const) = k1 and
k = k1 + k2
)
}
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
private predicate compares_ge(
Instruction test, Operand left, Operand right, int k, boolean isGe, boolean testIsTrue
Instruction test, Operand left, Operand right, int k, boolean isGe, AbstractValue value
) {
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue))
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, value))
}
/** Rearrange various simple comparisons into `left < right + k` form. */
@@ -595,55 +880,99 @@ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Ope
k = 1
}
private predicate complex_lt(
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
/** Rearrange various simple comparisons into `op < k` form. */
private predicate simple_comparison_lt(
Instruction test, Operand op, int k, boolean isLt, AbstractValue value
) {
sub_lt(cmp, left, right, k, isLt, testIsTrue)
exists(SwitchInstruction switch, CaseEdge case |
test = switch.getExpression() and
op.getDef() = test and
case = value.(MatchValue).getCase() and
exists(switch.getSuccessor(case)) and
case.getMaxValue() > case.getMinValue()
|
// op <= k => op < k - 1
isLt = true and
case.getMaxValue().toInt() = k - 1
or
isLt = false and
case.getMinValue().toInt() = k
)
}
private predicate complex_lt(
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, AbstractValue value
) {
sub_lt(cmp, left, right, k, isLt, value)
or
add_lt(cmp, left, right, k, isLt, testIsTrue)
add_lt(cmp, left, right, k, isLt, value)
}
private predicate complex_lt(
Instruction test, Operand left, int k, boolean isLt, AbstractValue value
) {
sub_lt(test, left, k, isLt, value)
or
add_lt(test, left, k, isLt, value)
}
// left - x < right + c => left < right + (c+x)
// left < (right - x) + c => left < right + (c-x)
private predicate sub_lt(
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, AbstractValue value
) {
exists(SubInstruction lhs, int c, int x |
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(SubInstruction rhs, int c, int x |
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
right = rhs.getLeftOperand() and
x = int_value(rhs.getRight()) and
k = c - x
)
or
exists(PointerSubInstruction lhs, int c, int x |
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(PointerSubInstruction rhs, int c, int x |
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
right = rhs.getLeftOperand() and
x = int_value(rhs.getRight()) and
k = c - x
)
}
private predicate sub_lt(Instruction test, Operand left, int k, boolean isLt, AbstractValue value) {
exists(SubInstruction lhs, int c, int x |
compares_lt(test, lhs.getAUse(), c, isLt, value) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(PointerSubInstruction lhs, int c, int x |
compares_lt(test, lhs.getAUse(), c, isLt, value) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
}
// left + x < right + c => left < right + (c-x)
// left < (right + x) + c => left < right + (c+x)
private predicate add_lt(
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, AbstractValue value
) {
exists(AddInstruction lhs, int c, int x |
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
@@ -653,7 +982,7 @@ private predicate add_lt(
)
or
exists(AddInstruction rhs, int c, int x |
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
(
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
or
@@ -663,7 +992,7 @@ private predicate add_lt(
)
or
exists(PointerAddInstruction lhs, int c, int x |
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
@@ -673,7 +1002,7 @@ private predicate add_lt(
)
or
exists(PointerAddInstruction rhs, int c, int x |
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
(
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
or
@@ -683,47 +1012,86 @@ private predicate add_lt(
)
}
private predicate add_lt(Instruction test, Operand left, int k, boolean isLt, AbstractValue value) {
exists(AddInstruction lhs, int c, int x |
compares_lt(test, lhs.getAUse(), c, isLt, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
) and
k = c - x
)
or
exists(PointerAddInstruction lhs, int c, int x |
compares_lt(test, lhs.getAUse(), c, isLt, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
) and
k = c - x
)
}
// left - x == right + c => left == right + (c+x)
// left == (right - x) + c => left == right + (c-x)
private predicate sub_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
exists(SubInstruction lhs, int c, int x |
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(SubInstruction rhs, int c, int x |
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
right = rhs.getLeftOperand() and
x = int_value(rhs.getRight()) and
k = c - x
)
or
exists(PointerSubInstruction lhs, int c, int x |
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(PointerSubInstruction rhs, int c, int x |
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
right = rhs.getLeftOperand() and
x = int_value(rhs.getRight()) and
k = c - x
)
}
// op - x == c => op == (c+x)
private predicate sub_eq(Instruction test, Operand op, int k, boolean areEqual, AbstractValue value) {
exists(SubInstruction sub, int c, int x |
compares_eq(test, sub.getAUse(), c, areEqual, value) and
op = sub.getLeftOperand() and
x = int_value(sub.getRight()) and
k = c + x
)
or
exists(PointerSubInstruction sub, int c, int x |
compares_eq(test, sub.getAUse(), c, areEqual, value) and
op = sub.getLeftOperand() and
x = int_value(sub.getRight()) and
k = c + x
)
}
// left + x == right + c => left == right + (c-x)
// left == (right + x) + c => left == right + (c+x)
private predicate add_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
exists(AddInstruction lhs, int c, int x |
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
@@ -733,7 +1101,7 @@ private predicate add_eq(
)
or
exists(AddInstruction rhs, int c, int x |
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
(
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
or
@@ -743,7 +1111,7 @@ private predicate add_eq(
)
or
exists(PointerAddInstruction lhs, int c, int x |
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
@@ -753,7 +1121,7 @@ private predicate add_eq(
)
or
exists(PointerAddInstruction rhs, int c, int x |
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
(
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
or
@@ -763,5 +1131,30 @@ private predicate add_eq(
)
}
// left + x == right + c => left == right + (c-x)
private predicate add_eq(
Instruction test, Operand left, int k, boolean areEqual, AbstractValue value
) {
exists(AddInstruction lhs, int c, int x |
compares_eq(test, lhs.getAUse(), c, areEqual, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
) and
k = c - x
)
or
exists(PointerAddInstruction lhs, int c, int x |
compares_eq(test, lhs.getAUse(), c, areEqual, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
) and
k = c - x
)
}
/** The int value of integer constant expression. */
private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() }

View File

@@ -28,6 +28,6 @@ import cpp
deprecated module DataFlow {
private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific
private import codeql.dataflow.DataFlow
import DataFlowMake<CppOldDataFlow>
import DataFlowMake<Location, CppOldDataFlow>
import semmle.code.cpp.dataflow.internal.DataFlowImpl1
}

View File

@@ -29,6 +29,6 @@ deprecated module TaintTracking {
private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific
private import semmle.code.cpp.dataflow.internal.TaintTrackingImplSpecific
private import codeql.dataflow.TaintTracking
import TaintFlowMake<CppOldDataFlow, CppOldTaintTracking>
import TaintFlowMake<Location, CppOldDataFlow, CppOldTaintTracking>
import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl
}

View File

@@ -2,6 +2,7 @@
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*/
private import semmle.code.cpp.Location
private import DataFlowImplSpecific
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<CppOldDataFlow>
import MakeImpl<Location, CppOldDataFlow>

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -2,6 +2,7 @@
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*/
private import semmle.code.cpp.Location
private import DataFlowImplSpecific
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<CppOldDataFlow>
import MakeImplCommon<Location, CppOldDataFlow>

View File

@@ -10,7 +10,7 @@ private import DataFlowImplSpecific
private import TaintTrackingImplSpecific
private import codeql.dataflow.internal.DataFlowImplConsistency
private module Input implements InputSig<CppOldDataFlow> {
private module Input implements InputSig<Location, CppOldDataFlow> {
predicate argHasPostUpdateExclude(Private::ArgumentNode n) {
// Is the null pointer (or something that's not really a pointer)
exists(n.asExpr().getValue())
@@ -26,4 +26,4 @@ private module Input implements InputSig<CppOldDataFlow> {
}
}
module Consistency = MakeConsistency<CppOldDataFlow, CppOldTaintTracking, Input>;
module Consistency = MakeConsistency<Location, CppOldDataFlow, CppOldTaintTracking, Input>;

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -4,6 +4,7 @@
* Provides C++-specific definitions for use in the data flow library.
*/
private import semmle.code.cpp.Location
private import codeql.dataflow.DataFlow
module Private {
@@ -15,7 +16,7 @@ module Public {
import DataFlowUtil
}
module CppOldDataFlow implements InputSig {
module CppOldDataFlow implements InputSig<Location> {
import Private
import Public

View File

@@ -105,7 +105,7 @@ class Node extends TNode {
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)

View File

@@ -4,9 +4,10 @@
* Provides C++-specific definitions for use in the taint tracking library.
*/
private import semmle.code.cpp.Location
private import codeql.dataflow.TaintTracking
private import DataFlowImplSpecific
module CppOldTaintTracking implements InputSig<CppOldDataFlow> {
module CppOldTaintTracking implements InputSig<Location, CppOldDataFlow> {
import TaintTrackingUtil
}

View File

@@ -28,6 +28,6 @@ import cpp
module DataFlow {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
private import codeql.dataflow.DataFlow
import DataFlowMake<CppDataFlow>
import DataFlowMake<Location, CppDataFlow>
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1
}

View File

@@ -27,6 +27,7 @@ module TaintTracking {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
private import codeql.dataflow.TaintTracking
import TaintFlowMake<CppDataFlow, CppTaintTracking>
private import semmle.code.cpp.Location
import TaintFlowMake<Location, CppDataFlow, CppTaintTracking>
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
}

View File

@@ -1322,3 +1322,31 @@ class CoYieldExpr extends UnaryOperation, @co_yield {
override int getPrecedence() { result = 2 }
}
/**
* An expression representing the re-use of another expression.
*
* In some specific cases an expression may be referred to outside its
* original context. A re-use expression wraps any such reference. A
* re-use expression can for example occur as the qualifier of an implicit
* destructor called on a temporary object, where the original use of the
* expression is in the definition of the temporary.
*/
class ReuseExpr extends Expr, @reuseexpr {
override string getAPrimaryQlClass() { result = "ReuseExpr" }
override string toString() { result = "reuse of " + this.getReusedExpr().toString() }
/**
* Gets the expression that is being re-used.
*/
Expr getReusedExpr() { expr_reuse(underlyingElement(this), unresolveElement(result), _) }
override Type getType() { result = this.getReusedExpr().getType() }
override predicate isLValueCategory() { expr_reuse(underlyingElement(this), _, 3) }
override predicate isXValueCategory() { expr_reuse(underlyingElement(this), _, 2) }
override predicate isPRValueCategory() { expr_reuse(underlyingElement(this), _, 1) }
}

View File

@@ -24,6 +24,6 @@ import cpp
module DataFlow {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
private import codeql.dataflow.DataFlow
import DataFlowMake<CppDataFlow>
import DataFlowMake<Location, CppDataFlow>
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1
}

View File

@@ -0,0 +1,20 @@
/**
* This file provides an abstract class that can be used to model additional
* object-to-field taint-flow.
*/
private import codeql.util.Unit
private import semmle.code.cpp.dataflow.new.DataFlow
/**
* A `Content` that should be implicitly regarded as tainted whenever an object with such `Content`
* is itself tainted.
*
* For example, if we had a type `struct Container { int field; }`, then by default a tainted
* `Container` and a `Container` with a tainted `int` stored in its `field` are distinct.
*
* If `any(DataFlow::FieldContent fc | fc.getField().hasQualifiedName("Container", "field"))` was
* included in this type however, then a tainted `Container` would imply that its `field` is also
* tainted (but not vice versa).
*/
abstract class TaintInheritingContent extends DataFlow::Content { }

View File

@@ -23,6 +23,6 @@ module TaintTracking {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
private import codeql.dataflow.TaintTracking
import TaintFlowMake<CppDataFlow, CppTaintTracking>
import TaintFlowMake<Location, CppDataFlow, CppTaintTracking>
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
}

View File

@@ -1,3 +1,4 @@
private import semmle.code.cpp.Location
private import DataFlowImplSpecific
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<CppDataFlow>
import MakeImpl<Location, CppDataFlow>

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -1,3 +1,4 @@
private import semmle.code.cpp.Location
private import DataFlowImplSpecific
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<CppDataFlow>
import MakeImplCommon<Location, CppDataFlow>

View File

@@ -8,7 +8,7 @@ private import DataFlowImplSpecific
private import TaintTrackingImplSpecific
private import codeql.dataflow.internal.DataFlowImplConsistency
private module Input implements InputSig<CppDataFlow> {
private module Input implements InputSig<Location, CppDataFlow> {
predicate argHasPostUpdateExclude(Private::ArgumentNode n) {
// The rules for whether an IR argument gets a post-update node are too
// complex to model here.
@@ -16,4 +16,4 @@ private module Input implements InputSig<CppDataFlow> {
}
}
module Consistency = MakeConsistency<CppDataFlow, CppTaintTracking, Input>;
module Consistency = MakeConsistency<Location, CppDataFlow, CppTaintTracking, Input>;

View File

@@ -3,6 +3,7 @@
*/
private import codeql.dataflow.DataFlow
private import semmle.code.cpp.Location
module Private {
import DataFlowPrivate
@@ -13,7 +14,7 @@ module Public {
import DataFlowUtil
}
module CppDataFlow implements InputSig {
module CppDataFlow implements InputSig<Location> {
import Private
import Public

View File

@@ -448,7 +448,7 @@ class Node extends TIRDataFlowNode {
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -1331,6 +1331,7 @@ private import GetConvertedResultExpression
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
not exprNodeShouldBeIndirectOperand(_, e, n) and
exists(Instruction def |
unique( | | getAUse(def)) = node.getOperand() and
e = getConvertedResultExpression(def, n)
@@ -1347,6 +1348,22 @@ private predicate indirectExprNodeShouldBeIndirectOperand(
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
exists(ArgumentOperand operand |
// When an argument (qualifier or positional) is a prvalue and the
// parameter (qualifier or positional) is a (const) reference, IR
// construction introduces a temporary `IRVariable`. The `VariableAddress`
// instruction has the argument as its `getConvertedResultExpression`
// result. However, the instruction actually represents the _address_ of
// the argument. So to fix this mismatch, we have the indirection of the
// `VariableAddressInstruction` map to the expression.
node.hasOperandAndIndirectionIndex(operand, 1) and
e = getConvertedResultExpression(operand.getDef(), n) and
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
)
}
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
exists(CallInstruction call |
call.getStaticCallTarget() instanceof Constructor and
@@ -1359,6 +1376,7 @@ private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node,
predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
not exprNodeShouldBeOperand(_, e, n) and
not exprNodeShouldBeIndirectOutNode(_, e, n) and
not exprNodeShouldBeIndirectOperand(_, e, n) and
e = getConvertedResultExpression(node.asInstruction(), n)
}
@@ -1391,7 +1409,8 @@ abstract private class ExprNodeBase extends Node {
private predicate exprNodeShouldBe(Expr e, int n) {
exprNodeShouldBeInstruction(_, e, n) or
exprNodeShouldBeOperand(_, e, n) or
exprNodeShouldBeIndirectOutNode(_, e, n)
exprNodeShouldBeIndirectOutNode(_, e, n) or
exprNodeShouldBeIndirectOperand(_, e, n)
}
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
@@ -1533,6 +1552,12 @@ private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgument
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
}
private class IndirectOperandExprNode extends ExprNodeBase instanceof IndirectOperand {
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
}
/**
* An expression, viewed as a node in a data flow graph.
*/
@@ -2276,8 +2301,8 @@ private import ContentStars
/** A reference through a non-union instance field. */
class FieldContent extends Content, TFieldContent {
Field f;
int indirectionIndex;
private Field f;
private int indirectionIndex;
FieldContent() { this = TFieldContent(f, indirectionIndex) }
@@ -2304,9 +2329,9 @@ class FieldContent extends Content, TFieldContent {
/** A reference through an instance field of a union. */
class UnionContent extends Content, TUnionContent {
Union u;
int indirectionIndex;
int bytes;
private Union u;
private int indirectionIndex;
private int bytes;
UnionContent() { this = TUnionContent(u, bytes, indirectionIndex) }

View File

@@ -103,6 +103,7 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
cached
private newtype TDefOrUseImpl =
TDefAddressImpl(BaseIRVariable v) or
TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
isDef(_, _, address, base, _, indirectionIndex)
} or
@@ -256,24 +257,64 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
}
abstract class DefImpl extends DefOrUseImpl {
Operand address;
int ind;
bindingset[ind]
DefImpl() { any() }
abstract int getIndirection();
abstract Node0Impl getValue();
abstract predicate isCertain();
Operand getAddressOperand() { result = address }
override int getIndirectionIndex() { result = ind }
override string toString() { result = "Def of " + this.getSourceVariable() }
abstract int getIndirection();
abstract predicate isCertain();
abstract Node0Impl getValue();
}
/** An initial definition of an `IRVariable`'s address. */
private class DefAddressImpl extends DefImpl, TDefAddressImpl {
BaseIRVariable v;
DefAddressImpl() {
this = TDefAddressImpl(v) and
ind = 0
}
final override int getIndirection() { result = 0 }
final override predicate isCertain() { any() }
final override Node0Impl getValue() { none() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
block = v.getIRVariable().getEnclosingIRFunction().getEntryBlock() and
index = 0
}
override Cpp::Location getLocation() { result = v.getIRVariable().getLocation() }
final override SourceVariable getSourceVariable() {
result.getBaseVariable() = v and
result.getIndirection() = 0
}
final override BaseSourceVariableInstruction getBase() { none() }
}
/**
* An SSA definition that has an associated `Operand` representing the address
* that is being written to.
*/
abstract private class OperandBasedDef extends DefImpl {
Operand address;
bindingset[ind]
OperandBasedDef() { any() }
Operand getAddressOperand() { result = address }
override Cpp::Location getLocation() { result = this.getAddressOperand().getUse().getLocation() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
@@ -281,7 +322,7 @@ abstract class DefImpl extends DefOrUseImpl {
}
}
private class DirectDef extends DefImpl, TDefImpl {
private class DirectDef extends OperandBasedDef, TDefImpl {
BaseSourceVariableInstruction base;
DirectDef() { this = TDefImpl(base, address, ind) }
@@ -295,7 +336,7 @@ private class DirectDef extends DefImpl, TDefImpl {
override predicate isCertain() { isDef(true, _, address, base, _, ind) }
}
private class IteratorDef extends DefImpl, TIteratorDef {
private class IteratorDef extends OperandBasedDef, TIteratorDef {
BaseSourceVariableInstruction container;
IteratorDef() { this = TIteratorDef(address, container, ind) }
@@ -1178,7 +1219,7 @@ class UseOrPhi extends SsaDefOrUse {
class Def extends DefOrUse {
override DefImpl defOrUse;
Operand getAddressOperand() { result = defOrUse.getAddressOperand() }
Operand getAddressOperand() { result = defOrUse.(OperandBasedDef).getAddressOperand() }
Instruction getAddress() { result = this.getAddressOperand().getDef() }

View File

@@ -4,7 +4,8 @@
private import codeql.dataflow.TaintTracking
private import DataFlowImplSpecific
private import semmle.code.cpp.Location
module CppTaintTracking implements InputSig<CppDataFlow> {
module CppTaintTracking implements InputSig<Location, CppDataFlow> {
import TaintTrackingUtil
}

View File

@@ -6,6 +6,7 @@ private import semmle.code.cpp.models.interfaces.SideEffect
private import DataFlowUtil
private import DataFlowPrivate
private import SsaInternals as Ssa
private import semmle.code.cpp.ir.dataflow.FlowSteps
/**
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
@@ -37,6 +38,12 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
)
or
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo)
or
// object->field conflation for content that is a `TaintInheritingContent`.
exists(DataFlow::ContentSet f |
readStep(nodeFrom, f, nodeTo) and
f.getAReadContent() instanceof TaintInheritingContent
)
}
/**

View File

@@ -90,6 +90,15 @@ class CaseEdge extends EdgeKind, TCaseEdge {
* Gets the largest value of the switch expression for which control will flow along this edge.
*/
final string getMaxValue() { result = maxValue }
/**
* Gets the unique value of the switch expression for which control will
* flow along this edge, if any.
*/
final string getValue() {
minValue = maxValue and
result = minValue
}
}
/**

View File

@@ -38,6 +38,12 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof BitOrInstruction and result = bitOr(left, right)
or
instr instanceof BitAndInstruction and result = bitAnd(left, right)
or
instr instanceof BitXorInstruction and result = bitXor(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)

View File

@@ -38,6 +38,12 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof BitOrInstruction and result = bitOr(left, right)
or
instr instanceof BitAndInstruction and result = bitAnd(left, right)
or
instr instanceof BitXorInstruction and result = bitXor(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)

View File

@@ -40,12 +40,43 @@ IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
result.getTag() = tag
}
/** Gets an operand of `op`. */
private Expr getAnOperand(Operation op) { result = op.getAnOperand() }
/**
* Gets the number of nested operands of `op`. For example,
* `getNumberOfNestedBinaryOperands((1 + 2) + 3))` is `3`.
*/
private int getNumberOfNestedBinaryOperands(Operation op) { result = count(getAnOperand*(op)) }
/**
* Holds if `op` should not be translated to a `ConstantInstruction` as part of
* IR generation, even if the value of `op` is constant.
*/
private predicate ignoreConstantValue(Operation op) {
op instanceof BitwiseAndExpr
or
op instanceof BitwiseOrExpr
or
op instanceof BitwiseXorExpr
}
/**
* Holds if `expr` is a constant of a type that can be replaced directly with
* its value in the IR. This does not include address constants as we have no
* means to express those as QL values.
*/
predicate isIRConstant(Expr expr) { exists(expr.getValue()) }
predicate isIRConstant(Expr expr) {
exists(expr.getValue()) and
// We avoid constant folding certain operations since it's often useful to
// mark one of those as a source in dataflow, and if the operation is
// constant folded it's not possible to mark its operands as a source (or
// sink).
// But to avoid creating an outrageous amount of IR from very large
// constant expressions we fall back to constant folding if the operation
// has more than 50 operands (i.e., 1 + 2 + 3 + 4 + ... + 50)
if ignoreConstantValue(expr) then getNumberOfNestedBinaryOperands(expr) > 50 else any()
}
// Pulled out for performance. See
// https://github.com/github/codeql-coreql-team/issues/1044.

View File

@@ -2769,6 +2769,50 @@ class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr,
final override Instruction getResult() { result = this.getTargetAddress() }
}
/**
* IR translation of a `ReuseExpr`.
*
* This translation produces a copy of the glvalue instruction holding the (unconverted) result
* of the reused expression. In the case where the original expression was a prvalue, the
* result will be a copy of the glvalue operand of a `TranslatedLoad`.
*/
class TranslatedReuseExpr extends TranslatedNonConstantExpr {
override ReuseExpr expr;
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
opcode instanceof Opcode::CopyValue and
tag instanceof OnlyInstructionTag and
resultType = this.getResultType()
}
override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind instanceof GotoEdge and
result = this.getParent().getChildSuccessor(this, kind)
}
override TranslatedElement getChildInternal(int id) { none() }
override Instruction getALastInstructionInternal() {
result = this.getInstruction(OnlyInstructionTag())
}
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag instanceof UnaryOperandTag and
if getTranslatedExpr(expr.getReusedExpr()) instanceof TranslatedLoad
then result = getTranslatedExpr(expr.getReusedExpr()).(TranslatedLoad).getOperand().getResult()
else result = getTranslatedExpr(expr.getReusedExpr()).getResult()
}
}
/**
* IR translation of a `throw` expression.
*/

View File

@@ -38,6 +38,12 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof BitOrInstruction and result = bitOr(left, right)
or
instr instanceof BitAndInstruction and result = bitAnd(left, right)
or
instr instanceof BitXorInstruction and result = bitXor(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)

View File

@@ -89,6 +89,18 @@ int compareLE(int a, int b) { if a <= b then result = 1 else result = 0 }
bindingset[a, b]
int compareGE(int a, int b) { if a >= b then result = 1 else result = 0 }
/** Returns `a | b`. */
bindingset[a, b]
int bitOr(int a, int b) { result = a.bitOr(b) }
/** Returns `a & b`. */
bindingset[a, b]
int bitAnd(int a, int b) { result = a.bitAnd(b) }
/** Returns `a ^ b`. */
bindingset[a, b]
int bitXor(int a, int b) { result = a.bitXor(b) }
/**
* Returns `-a`. If the negation would overflow, there is no result.
*/

View File

@@ -36,7 +36,9 @@ private class MallocAllocationFunction extends AllocationFunction {
"CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line)
"CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line)
"CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line)
"CRYPTO_secure_zalloc" // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
"CRYPTO_secure_zalloc", // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
"g_malloc", // g_malloc (n_bytes);
"g_try_malloc" // g_try_malloc(n_bytes);
]) and
sizeArg = 0
or
@@ -139,7 +141,9 @@ private class ReallocAllocationFunction extends AllocationFunction, TaintFunctio
// --- Windows COM allocation
"CoTaskMemRealloc", // CoTaskMemRealloc(ptr, size)
// --- OpenSSL memory allocation
"CRYPTO_realloc" // CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
"CRYPTO_realloc", // CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
"g_realloc", // g_realloc(mem, n_bytes);
"g_try_realloc" // g_try_realloc(mem, n_bytes);
]) and
sizeArg = 1 and
reallocArg = 0

View File

@@ -20,8 +20,10 @@ private class StandardDeallocationFunction extends DeallocationFunction {
freedArg = 0
or
this.hasGlobalName([
// --- OpenSSL memory allocation
"CRYPTO_free", "CRYPTO_secure_free"
// --- OpenSSL memory deallocation
"CRYPTO_free", "CRYPTO_secure_free",
// --- glib memory deallocation
"g_free"
]) and
freedArg = 0
or

View File

@@ -9,6 +9,8 @@ import cpp
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* An instantiation of the `std::iterator_traits` template.
@@ -438,7 +440,7 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
* A `begin` or `end` member function, or a related member function, that
* returns an iterator.
*/
private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction {
class BeginOrEndFunction extends MemberFunction {
BeginOrEndFunction() {
this.hasName([
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
@@ -446,7 +448,11 @@ private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetItera
]) and
this.getType().getUnspecifiedType() instanceof Iterator
}
}
private class BeginOrEndFunctionModels extends BeginOrEndFunction, TaintFunction,
GetIteratorFunction, AliasFunction, SideEffectFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
@@ -456,6 +462,22 @@ private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetItera
input.isQualifierObject() and
output.isReturnValue()
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
none()
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
/**

View File

@@ -253,13 +253,15 @@ private class StdSequenceContainerAssign extends TaintFunction {
/**
* The standard container functions `at` and `operator[]`.
*/
private class StdSequenceContainerAt extends TaintFunction {
class StdSequenceContainerAt extends MemberFunction {
StdSequenceContainerAt() {
this.getClassAndName(["at", "operator[]"]) instanceof Array or
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
this.getClassAndName(["at", "operator[]"]) instanceof Vector
}
}
private class StdSequenceContainerAtModel extends StdSequenceContainerAt, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
input.isQualifierObject() and

View File

@@ -129,9 +129,11 @@ private class StdMapMerge extends TaintFunction {
/**
* The standard map functions `at` and `operator[]`.
*/
private class StdMapAt extends TaintFunction {
class StdMapAt extends MemberFunction {
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
}
private class StdMapAtModels extends StdMapAt, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
input.isQualifierObject() and

View File

@@ -1513,6 +1513,12 @@ exprs(
int location: @location_expr ref
);
expr_reuse(
int reuse: @expr ref,
int original: @expr ref,
int value_category: int ref
)
/*
case @value.category of
1 = prval
@@ -1741,6 +1747,7 @@ case @expr.kind of
| 360 = @isunsigned
| 361 = @isvoid
| 362 = @isvolatile
| 363 = @reuseexpr
;
@var_args_expr = @vastartexpr

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Introduce re-use expressions
compatibility: backwards

View File

@@ -0,0 +1,7 @@
class Expr extends @expr {
string toString() { none() }
}
from Expr reuse, Expr original, int value_category
where expr_reuse(reuse, original) and expr_types(original, _, value_category)
select reuse, original, value_category

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add value category to expr_reuse table
compatibility: full
expr_reuse.rel: run expr_reuse.qlo

View File

@@ -1,3 +1,34 @@
## 0.9.9
### New Queries
* Added a new query, `cpp/type-confusion`, to detect casts to invalid types.
### Query Metadata Changes
* `@precision medium` metadata was added to the `cpp/boost/tls-settings-misconfiguration` and `cpp/boost/use-of-deprecated-hardcoded-security-protocol` queries, and these queries are now included in the security-extended suite. The `@name` metadata of these queries were also updated.
### Minor Analysis Improvements
* The "Missing return-value check for a 'scanf'-like function" query (`cpp/missing-check-scanf`) has been converted to a `path-problem` query.
* The "Potentially uninitialized local variable" query (`cpp/uninitialized-local`) has been converted to a `path-problem` query.
* Added models for `GLib` allocation and deallocation functions.
## 0.9.8
No user-facing changes.
## 0.9.7
No user-facing changes.
## 0.9.6
### Minor Analysis Improvements
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.
## 0.9.5
### Minor Analysis Improvements

View File

@@ -2,7 +2,7 @@
* @name Missing return-value check for a 'scanf'-like function
* @description Failing to check that a call to 'scanf' actually writes to an
* output variable can lead to unexpected behavior at reading time.
* @kind problem
* @kind path-problem
* @problem.severity warning
* @security-severity 7.5
* @precision medium
@@ -18,16 +18,9 @@ import semmle.code.cpp.commons.Scanf
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.ValueNumbering
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import ScanfChecks
/** Holds if `n` reaches an argument to a call to a `scanf`-like function. */
pragma[nomagic]
predicate revFlow0(Node n) {
isSink(_, _, n, _)
or
exists(Node succ | revFlow0(succ) | localFlowStep(n, succ))
}
import ScanfToUseFlow::PathGraph
/**
* Holds if `n` represents an uninitialized stack-allocated variable, or a
@@ -38,30 +31,45 @@ predicate isUninitialized(Node n) {
n.asIndirectExpr(1) instanceof AllocationExpr
}
pragma[nomagic]
predicate fwdFlow0(Node n) {
revFlow0(n) and
(
isUninitialized(n)
or
exists(Node prev |
fwdFlow0(prev) and
localFlowStep(prev, n)
)
)
}
predicate isSink(ScanfFunctionCall call, int index, Node n, Expr input) {
input = call.getOutputArgument(index) and
n.asIndirectExpr() = input
}
/**
* A configuration to track a uninitialized data flowing to a `scanf`-like
* output parameter position.
*
* This is meant to be a simple flow to rule out cases like:
* ```
* int x = 0;
* scanf(..., &x);
* use(x);
* ```
* since `x` is already initialized it's not a security concern that `x` is
* used without checking the return value of `scanf`.
*
* Since this flow is meant to be simple, we disable field flow and require the
* source and the sink to be in the same callable.
*/
module UninitializedToScanfConfig implements ConfigSig {
predicate isSource(Node source) { isUninitialized(source) }
predicate isSink(Node sink) { isSink(_, _, sink, _) }
FlowFeature getAFeature() { result instanceof FeatureEqualSourceSinkCallContext }
int accessPathLimit() { result = 0 }
}
module UninitializedToScanfFlow = Global<UninitializedToScanfConfig>;
/**
* Holds if `call` is a `scanf`-like call and `output` is the `index`'th
* argument that has not been previously initialized.
*/
predicate isRelevantScanfCall(ScanfFunctionCall call, int index, Expr output) {
exists(Node n | fwdFlow0(n) and isSink(call, index, n, output)) and
exists(Node n | UninitializedToScanfFlow::flowTo(n) and isSink(call, index, n, output)) and
// Exclude results from incorrectky checked scanf query
not incorrectlyCheckedScanf(call)
}
@@ -77,31 +85,6 @@ predicate isSource(ScanfFunctionCall call, int index, Node n, Expr output) {
n.asDefiningArgument() = output
}
/**
* Holds if `n` is reachable from an output argument of a relevant call to
* a `scanf`-like function.
*/
pragma[nomagic]
predicate fwdFlow(Node n) {
isSource(_, _, n, _)
or
exists(Node prev |
fwdFlow(prev) and
localFlowStep(prev, n) and
not isSanitizerOut(prev)
)
}
/** Holds if `n` should not have outgoing flow. */
predicate isSanitizerOut(Node n) {
// We disable flow out of sinks to reduce result duplication
isSink(n, _)
or
// If the node is being passed to a function it may be
// modified, and thus it's safe to later read the value.
exists(n.asIndirectArgument())
}
/**
* Holds if `n` is a node such that `n.asExpr() = e` and `e` is not an
* argument of a deallocation expression.
@@ -112,40 +95,37 @@ predicate isSink(Node n, Expr e) {
}
/**
* Holds if `n` is part of a path from a call to a `scanf`-like function
* to a use of the written variable.
* A configuration to track flow from the output argument of a call to a
* `scanf`-like function, and to a use of the defined variable.
*/
pragma[nomagic]
predicate revFlow(Node n) {
fwdFlow(n) and
(
module ScanfToUseConfig implements ConfigSig {
predicate isSource(Node source) { isSource(_, _, source, _) }
predicate isSink(Node sink) { isSink(sink, _) }
predicate isBarrierOut(Node n) {
// We disable flow out of sinks to reduce result duplication
isSink(n, _)
or
exists(Node succ |
revFlow(succ) and
localFlowStep(n, succ) and
not isSanitizerOut(n)
)
)
// If the node is being passed to a function it may be
// modified, and thus it's safe to later read the value.
exists(n.asIndirectArgument())
}
}
/** A local flow step, restricted to relevant dataflow nodes. */
private predicate step(Node n1, Node n2) {
revFlow(n1) and
revFlow(n2) and
localFlowStep(n1, n2)
}
predicate hasFlow(Node n1, Node n2) = fastTC(step/2)(n1, n2)
module ScanfToUseFlow = Global<ScanfToUseConfig>;
/**
* Holds if `source` is the `index`'th argument to the `scanf`-like call `call`, and `sink` is
* a dataflow node that represents the expression `e`.
*/
predicate hasFlow(Node source, ScanfFunctionCall call, int index, Node sink, Expr e) {
isSource(call, index, source, _) and
hasFlow(source, sink) and
isSink(sink, e)
predicate flowPath(
ScanfToUseFlow::PathNode source, ScanfFunctionCall call, int index, ScanfToUseFlow::PathNode sink,
Expr e
) {
isSource(call, index, source.getNode(), _) and
ScanfToUseFlow::flowPath(source, sink) and
isSink(sink.getNode(), e)
}
/**
@@ -167,39 +147,33 @@ int getMinimumGuardConstant(ScanfFunctionCall call, int index) {
* Holds the access to `e` isn't guarded by a check that ensures that `call` returned
* at least `minGuard`.
*/
predicate hasNonGuardedAccess(ScanfFunctionCall call, Expr e, int minGuard) {
predicate hasNonGuardedAccess(
ScanfToUseFlow::PathNode source, ScanfFunctionCall call, ScanfToUseFlow::PathNode sink, Expr e,
int minGuard
) {
exists(int index |
hasFlow(_, call, index, _, e) and
flowPath(source, call, index, sink, e) and
minGuard = getMinimumGuardConstant(call, index)
|
not exists(int value |
e.getBasicBlock() = blockGuardedBy(value, "==", call) and minGuard <= value
not exists(GuardCondition guard |
// call == k and k >= minGuard so call >= minGuard
guard
.ensuresEq(globalValueNumber(call).getAnExpr(), any(int k | minGuard <= k),
e.getBasicBlock(), true)
or
e.getBasicBlock() = blockGuardedBy(value, "<", call) and minGuard - 1 <= value
or
e.getBasicBlock() = blockGuardedBy(value, "<=", call) and minGuard <= value
// call >= k and k >= minGuard so call >= minGuard
guard
.ensuresLt(globalValueNumber(call).getAnExpr(), any(int k | minGuard <= k),
e.getBasicBlock(), false)
)
)
}
/** Returns a block guarded by the assertion of `value op call` */
BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
exists(GuardCondition g, Expr left, Expr right |
right = g.getAChild() and
value = left.getValue().toInt() and
localExprFlow(call, right)
|
g.ensuresEq(left, right, 0, result, true) and op = "=="
or
g.ensuresLt(left, right, 0, result, true) and op = "<"
or
g.ensuresLt(left, right, 1, result, true) and op = "<="
)
}
from ScanfFunctionCall call, Expr e, int minGuard
where hasNonGuardedAccess(call, e, minGuard)
select e,
from
ScanfToUseFlow::PathNode source, ScanfToUseFlow::PathNode sink, ScanfFunctionCall call, Expr e,
int minGuard
where hasNonGuardedAccess(source, call, sink, e, minGuard)
select e, source, sink,
"This variable is read, but may not have been written. " +
"It should be guarded by a check that the $@ returns at least " + minGuard + ".", call,
call.toString()

View File

@@ -3,15 +3,11 @@ private import semmle.code.cpp.commons.Scanf
private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.ir.ValueNumbering
private ConstantInstruction getZeroInstruction() { result.getValue() = "0" }
private Operand zero() { result.getDef() = getZeroInstruction() }
private predicate exprInBooleanContext(Expr e) {
exists(IRGuardCondition gc |
exists(Instruction i |
i.getUnconvertedResultExpression() = e and
gc.comparesEq(valueNumber(i).getAUse(), zero(), 0, _, _)
gc.comparesEq(valueNumber(i).getAUse(), 0, _, _)
)
or
gc.getUnconvertedResultExpression() = e
@@ -36,10 +32,6 @@ private string getEofValue() {
)
}
private ConstantInstruction getEofInstruction() { result.getValue() = getEofValue() }
private Operand eof() { result.getDef() = getEofInstruction() }
/**
* Holds if the value of `call` has been checked to not equal `EOF`.
*/
@@ -47,10 +39,10 @@ private predicate checkedForEof(ScanfFunctionCall call) {
exists(IRGuardCondition gc |
exists(Instruction i | i.getUnconvertedResultExpression() = call |
// call == EOF
gc.comparesEq(valueNumber(i).getAUse(), eof(), 0, _, _)
gc.comparesEq(valueNumber(i).getAUse(), getEofValue().toInt(), _, _)
or
// call < 0 (EOF is guaranteed to be negative)
gc.comparesLt(valueNumber(i).getAUse(), zero(), 0, true, _)
gc.comparesLt(valueNumber(i).getAUse(), 0, true, _)
)
)
}

View File

@@ -37,6 +37,37 @@ class UncalledFunction extends Function {
}
}
/** The `unsigned short` type. */
class UnsignedShort extends ShortType {
UnsignedShort() { this.isUnsigned() }
}
/**
* Holds if `t` cannot refer to a string. That is, it's a built-in
* or arithmetic type that is not a "`char` like" type.
*/
predicate cannotContainString(Type t) {
exists(Type unspecified |
unspecified = t.getUnspecifiedType() and
not unspecified instanceof UnknownType and
not unspecified instanceof CharType and
not unspecified instanceof WideCharType and
not unspecified instanceof Char8Type and
not unspecified instanceof Char16Type and
not unspecified instanceof Char32Type and
// C often defines `wchar_t` as `unsigned short`
not unspecified instanceof UnsignedShort
|
unspecified instanceof ArithmeticType or
unspecified instanceof BuiltInType
)
}
predicate dataFlowOrTaintFlowFunction(Function func, FunctionOutput output) {
func.(DataFlowFunction).hasDataFlow(_, output) or
func.(TaintFunction).hasTaintFlow(_, output)
}
/**
* Holds if `node` is a non-constant source of data flow for non-const format string detection.
* This is defined as either:
@@ -69,7 +100,9 @@ predicate isNonConst(DataFlow::Node node) {
// Parameters of uncalled functions that aren't const
exists(UncalledFunction f, Parameter p |
f.getAParameter() = p and
p = node.asParameter() and
// We pick the indirection of the parameter since this query is focused
// on strings.
p = node.asParameter(1) and
// Ignore main's argv parameter as it is already considered a `FlowSource`
// not ignoring it will result in path redundancies
(f.getName() = "main" implies p != f.getParameter(1))
@@ -82,30 +115,27 @@ predicate isNonConst(DataFlow::Node node) {
// are considered as possible non-const sources
// The function's output must also not be const to be considered a non-const source
exists(Function func, CallInstruction call |
// NOTE: could use `Call` getAnArgument() instead of `CallInstruction` but requires two
// variables representing the same call in ordoer to use `callOutput` below.
exists(Expr arg |
call.getPositionalArgumentOperand(_).getDef().getUnconvertedResultExpression() = arg and
arg = node.asDefiningArgument()
)
or
call.getUnconvertedResultExpression() = node.asIndirectExpr()
not func.hasDefinition() and
func = call.getStaticCallTarget()
|
func = call.getStaticCallTarget() and
// Case 1: It's a known dataflow or taintflow function with flow to the return value
call.getUnconvertedResultExpression() = node.asIndirectExpr() and
not exists(FunctionOutput output |
// NOTE: we must include dataflow and taintflow. e.g., including only dataflow we will find sprintf
// variant function's output are now possible non-const sources
pragma[only_bind_out](func).(DataFlowFunction).hasDataFlow(_, output) or
pragma[only_bind_out](func).(TaintFunction).hasTaintFlow(_, output)
|
dataFlowOrTaintFlowFunction(func, output) and
output.isReturnValueDeref(_) and
node = callOutput(call, output)
)
) and
not exists(Call c |
c.getTarget().hasDefinition() and
if node instanceof DataFlow::DefinitionByReferenceNode
then c.getAnArgument() = node.asDefiningArgument()
else c = [node.asExpr(), node.asIndirectExpr()]
or
// Case 2: It's a known dataflow or taintflow function with flow to an output parameter
exists(int i |
call.getPositionalArgumentOperand(i).getDef().getUnconvertedResultExpression() =
node.asDefiningArgument() and
not exists(FunctionOutput output |
dataFlowOrTaintFlowFunction(func, output) and
output.isParameterDeref(i, _) and
node = callOutput(call, output)
)
)
)
}
@@ -114,18 +144,29 @@ predicate isNonConst(DataFlow::Node node) {
* `FormattingFunctionCall`.
*/
predicate isSinkImpl(DataFlow::Node sink, Expr formatString) {
[sink.asExpr(), sink.asIndirectExpr()] = formatString and
sink.asIndirectExpr() = formatString and
exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex()))
}
module NonConstFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isNonConst(source) }
predicate isSource(DataFlow::Node source) {
exists(Type t |
isNonConst(source) and
t = source.getType() and
not cannotContainString(t)
)
}
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
predicate isBarrier(DataFlow::Node node) {
// Ignore tracing non-const through array indices
exists(ArrayExpr a | a.getArrayOffset() = node.asExpr())
exists(ArrayExpr a | a.getArrayOffset() = node.asIndirectExpr())
or
exists(Type t |
t = node.getType() and
cannotContainString(t)
)
}
}

View File

@@ -2,7 +2,7 @@
* @name Potentially uninitialized local variable
* @description Reading from a local variable that has not been assigned to
* will typically yield garbage.
* @kind problem
* @kind path-problem
* @id cpp/uninitialized-local
* @problem.severity warning
* @security-severity 7.8
@@ -15,6 +15,7 @@
import cpp
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.MustFlow
import PathGraph
/**
* Auxiliary predicate: Types that don't require initialization
@@ -89,4 +90,4 @@ where
conf.hasFlowPath(source, sink) and
isSinkImpl(sink.getInstruction(), va) and
v = va.getTarget()
select va, "The variable $@ may not be initialized at this access.", v, v.getName()
select va, source, sink, "The variable $@ may not be initialized at this access.", v, v.getName()

View File

@@ -1,8 +1,9 @@
/**
* @name Boost_asio TLS Settings Misconfiguration
* @name boost::asio TLS settings misconfiguration
* @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols.
* @kind problem
* @problem.severity error
* @precision medium
* @security-severity 7.5
* @id cpp/boost/tls-settings-misconfiguration
* @tags security
@@ -12,34 +13,41 @@
import cpp
import semmle.code.cpp.security.boostorg.asio.protocols
module ExistsAnyFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr())
}
predicate isSourceImpl(DataFlow::Node source, ConstructorCall cc) {
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = cc and cc = source.asExpr())
}
predicate isSink(DataFlow::Node sink) {
exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions |
f.getACallToThisFunction() = fcSetOptions and
fcSetOptions.getQualifier() = sink.asExpr()
)
}
predicate isSinkImpl(DataFlow::Node sink, FunctionCall fcSetOptions) {
exists(BoostorgAsio::SslSetOptionsFunction f |
f.getACallToThisFunction() = fcSetOptions and
fcSetOptions.getQualifier() = sink.asIndirectExpr()
)
}
module ExistsAnyFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
}
module ExistsAnyFlow = DataFlow::Global<ExistsAnyFlowConfig>;
bindingset[flag]
predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
exists(VariableAccess contextSetOptions |
ExistsAnyFlow::flow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
contextSetOptions = fcSetOptions.getQualifier() and
forall(Expr optionArgument, Expr optionArgumentSource |
optionArgument = fcSetOptions.getArgument(0) and
BoostorgAsio::SslOptionFlow::flow(DataFlow::exprNode(optionArgumentSource),
DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
exists(
VariableAccess contextSetOptions, BoostorgAsio::SslSetOptionsFunction f, DataFlow::Node source,
DataFlow::Node sink
|
isSourceImpl(source, cc) and
isSinkImpl(sink, fcSetOptions) and
ExistsAnyFlow::flow(source, sink) and
f.getACallToThisFunction() = fcSetOptions and
contextSetOptions = fcSetOptions.getQualifier() and
forex(Expr optionArgument |
optionArgument = fcSetOptions.getArgument(0) and
BoostorgAsio::SslOptionFlow::flowTo(DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
)
}

View File

@@ -1,8 +1,9 @@
/**
* @name boost::asio Use of deprecated hardcoded Protocol
* @name boost::asio use of deprecated hardcoded protocol
* @description Using a deprecated hard-coded protocol using the boost::asio library.
* @kind problem
* @problem.severity error
* @precision medium
* @security-severity 7.5
* @id cpp/boost/use-of-deprecated-hardcoded-security-protocol
* @tags security

View File

@@ -0,0 +1,50 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Certain casts in C and C++ place no restrictions on the target type. For
example, C style casts such as <code>(MyClass*)p</code> allows the programmer
to cast any pointer <code>p</code> to an expression of type <code>MyClass*</code>.
If the runtime type of <code>p</code> turns out to be a type that's incompatible
with <code>MyClass</code>, this results in undefined behavior.
</p>
</overview>
<recommendation>
<p>
If possible, use <code>dynamic_cast</code> to safely cast between polymorphic types.
If <code>dynamic_cast</code> is not an option, use <code>static_cast</code> to restrict
the kinds of conversions that the compiler is allowed to perform. If C++ style casts is
not an option, carefully check that all casts are safe.
</p>
</recommendation>
<example>
<p>
Consider the following class hierachy where we define a base class <code>Shape</code> and two
derived classes <code>Circle</code> and <code>Square</code> that are mutually incompatible:
</p>
<sample src="TypeConfusionCommon.cpp"/>
<p>
The following code demonstrates a type confusion vulnerability where the programmer
assumes that the runtime type of <code>p</code> is always a <code>Square</code>.
However, if <code>p</code> is a <code>Circle</code>, the cast will result in undefined behavior.
</p>
<sample src="TypeConfusionBad.cpp"/>
<p>
The following code fixes the vulnerability by using <code>dynamic_cast</code> to
safely cast between polymorphic types. If the cast fails, <code>dynamic_cast</code>
returns a null pointer, which can be checked for and handled appropriately.
</p>
<sample src="TypeConfusionGood.cpp"/>
</example>
<references>
<li>
Microsoft Learn: <a href="https://learn.microsoft.com/en-us/cpp/cpp/type-conversions-and-type-safety-modern-cpp">Type conversions and type safety</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,263 @@
/**
* @name Type confusion
* @description Casting a value to an incompatible type can lead to undefined behavior.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision medium
* @id cpp/type-confusion
* @tags security
* external/cwe/cwe-843
*/
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import Flow::PathGraph
/**
* Holds if `f` is a field located at byte offset `offset` in `c`.
*
* Note that predicate is recursive, so that given the following:
* ```cpp
* struct S1 {
* int a;
* void* b;
* };
*
* struct S2 {
* S1 s1;
* char c;
* };
* ```
* both `hasAFieldWithOffset(S2, s1, 0)` and `hasAFieldWithOffset(S2, a, 0)`
* holds.
*/
predicate hasAFieldWithOffset(Class c, Field f, int offset) {
// Base case: `f` is a field in `c`.
f = c.getAField() and
offset = f.getByteOffset() and
not f.getUnspecifiedType().(Class).hasDefinition()
or
// Otherwise, we find the struct that is a field of `c` which then has
// the field `f` as a member.
exists(Field g |
g = c.getAField() and
// Find the field with the largest offset that's less than or equal to
// offset. That's the struct we need to search recursively.
g =
max(Field cand, int candOffset |
cand = c.getAField() and
candOffset = cand.getByteOffset() and
offset >= candOffset
|
cand order by candOffset
) and
hasAFieldWithOffset(g.getUnspecifiedType(), f, offset - g.getByteOffset())
)
}
/** Holds if `f` is the last field of its declaring class. */
predicate lastField(Field f) {
exists(Class c | c = f.getDeclaringType() |
f =
max(Field cand, int byteOffset |
cand.getDeclaringType() = c and byteOffset = f.getByteOffset()
|
cand order by byteOffset
)
)
}
/**
* Holds if there exists a field in `c2` at offset `offset` that's compatible
* with `f1`.
*/
bindingset[f1, offset, c2]
pragma[inline_late]
predicate hasCompatibleFieldAtOffset(Field f1, int offset, Class c2) {
exists(Field f2 | hasAFieldWithOffset(c2, f2, offset) |
// Let's not deal with bit-fields for now.
f2 instanceof BitField
or
f1.getUnspecifiedType().getSize() = f2.getUnspecifiedType().getSize()
or
lastField(f1) and
f1.getUnspecifiedType().getSize() <= f2.getUnspecifiedType().getSize()
)
}
/**
* Holds if `c1` is a prefix of `c2`.
*/
bindingset[c1, c2]
pragma[inline_late]
predicate prefix(Class c1, Class c2) {
not c1.isPolymorphic() and
not c2.isPolymorphic() and
if c1 instanceof Union
then
// If it's a union we just verify that one of it's variants is compatible with the other class
exists(Field f1, int offset |
// Let's not deal with bit-fields for now.
not f1 instanceof BitField and
hasAFieldWithOffset(c1, f1, offset)
|
hasCompatibleFieldAtOffset(f1, offset, c2)
)
else
forall(Field f1, int offset |
// Let's not deal with bit-fields for now.
not f1 instanceof BitField and
hasAFieldWithOffset(c1, f1, offset)
|
hasCompatibleFieldAtOffset(f1, offset, c2)
)
}
/**
* An unsafe cast is any explicit cast that is not
* a `dynamic_cast`.
*/
class UnsafeCast extends Cast {
private Class toType;
UnsafeCast() {
(
this instanceof CStyleCast
or
this instanceof StaticCast
or
this instanceof ReinterpretCast
) and
toType = this.getExplicitlyConverted().getUnspecifiedType().stripType() and
not this.isImplicit() and
exists(TypeDeclarationEntry tde |
tde = toType.getDefinition() and
not tde.isFromUninstantiatedTemplate(_)
)
}
Class getConvertedType() { result = toType }
/**
* Holds if the result of this cast can safely be interpreted as a value of
* type `t`.
*
* The compatibility rules are as follows:
*
* 1. the result of `(T)x` is compatible with the type `T` for any `T`
* 2. the result of `(T)x` is compatible with the type `U` for any `U` such
* that `U` is a subtype of `T`, or `T` is a subtype of `U`.
* 3. the result of `(T)x` is compatible with the type `U` if the list
* of fields of `T` is a prefix of the list of fields of `U`.
* For example, if `U` is `struct { unsigned char x; int y; };`
* and `T` is `struct { unsigned char uc; };`.
* 4. the result of `(T)x` is compatible with the type `U` if the list
* of fields of `U` is a prefix of the list of fields of `T`.
*
* Condition 4 is a bit controversial, since it assumes that the additional
* fields in `T` won't be accessed. This may result in some FNs.
*/
bindingset[this, t]
pragma[inline_late]
predicate compatibleWith(Type t) {
// Conition 1
t.stripType() = this.getConvertedType()
or
// Condition 3
prefix(this.getConvertedType(), t.stripType())
or
// Condition 4
prefix(t.stripType(), this.getConvertedType())
or
// Condition 2 (a)
t.stripType().(Class).getABaseClass+() = this.getConvertedType()
or
// Condition 2 (b)
t.stripType() = this.getConvertedType().getABaseClass+()
}
}
/**
* Holds if `source` is an allocation that allocates a value of type `type`.
*/
predicate isSourceImpl(DataFlow::Node source, Class type) {
exists(AllocationExpr alloc |
alloc = source.asExpr() and
type = alloc.getAllocatedElementType().stripType() and
not exists(
alloc
.(NewOrNewArrayExpr)
.getAllocator()
.(OperatorNewAllocationFunction)
.getPlacementArgument()
)
) and
exists(TypeDeclarationEntry tde |
tde = type.getDefinition() and
not tde.isFromUninstantiatedTemplate(_)
)
}
/** A configuration describing flow from an allocation to a potentially unsafe cast. */
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
predicate isBarrier(DataFlow::Node node) {
// We disable flow through global variables to reduce FPs from infeasible paths
node instanceof DataFlow::VariableNode
or
exists(Class c | c = node.getType().stripType() |
not c.hasDefinition()
or
exists(TypeDeclarationEntry tde |
tde = c.getDefinition() and
tde.isFromUninstantiatedTemplate(_)
)
)
}
predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(UnsafeCast cast).getUnconverted() }
int fieldFlowBranchLimit() { result = 0 }
}
module Flow = DataFlow::Global<Config>;
predicate relevantType(DataFlow::Node sink, Class allocatedType) {
exists(DataFlow::Node source |
Flow::flow(source, sink) and
isSourceImpl(source, allocatedType)
)
}
predicate isSinkImpl(
DataFlow::Node sink, Class allocatedType, Type convertedType, boolean compatible
) {
exists(UnsafeCast cast |
relevantType(sink, allocatedType) and
sink.asExpr() = cast.getUnconverted() and
convertedType = cast.getConvertedType()
|
if cast.compatibleWith(allocatedType) then compatible = true else compatible = false
)
}
from
Flow::PathNode source, Flow::PathNode sink, Type badSourceType, Type sinkType,
DataFlow::Node sinkNode
where
Flow::flowPath(source, sink) and
sinkNode = sink.getNode() and
isSourceImpl(source.getNode(), badSourceType) and
isSinkImpl(sinkNode, badSourceType, sinkType, false) and
// If there is any flow that would result in a valid cast then we don't
// report an alert here. This reduces the number of FPs from infeasible paths
// significantly.
not exists(DataFlow::Node goodSource, Type goodSourceType |
isSourceImpl(goodSource, goodSourceType) and
isSinkImpl(sinkNode, goodSourceType, sinkType, true) and
Flow::flow(goodSource, sinkNode)
)
select sinkNode, source, sink, "Conversion from $@ to $@ is invalid.", badSourceType,
badSourceType.toString(), sinkType, sinkType.toString()

View File

@@ -0,0 +1,7 @@
void allocate_and_draw_bad() {
Shape* shape = new Circle;
// ...
// BAD: Assumes that shape is always a Square
Square* square = static_cast<Square*>(shape);
int length = square->getLength();
}

View File

@@ -0,0 +1,25 @@
struct Shape {
virtual ~Shape();
virtual void draw() = 0;
};
struct Circle : public Shape {
Circle();
void draw() override {
/* ... */
}
int getRadius();
};
struct Square : public Shape {
Square();
void draw() override {
/* ... */
}
int getLength();
};

View File

@@ -0,0 +1,11 @@
void allocate_and_draw_good() {
Shape* shape = new Circle;
// ...
// GOOD: Dynamically checks if shape is a Square
Square* square = dynamic_cast<Square*>(shape);
if(square) {
int length = square->getLength();
} else {
// handle error
}
}

View File

@@ -4,6 +4,7 @@
* @kind metric
* @tags summary
* lines-of-code
* debug
* @id cpp/summary/lines-of-user-code
*/

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.

View File

@@ -1,4 +1,6 @@
---
category: minorAnalysis
---
## 0.9.6
### Minor Analysis Improvements
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
## 0.9.9
### New Queries
* Added a new query, `cpp/type-confusion`, to detect casts to invalid types.
### Query Metadata Changes
* `@precision medium` metadata was added to the `cpp/boost/tls-settings-misconfiguration` and `cpp/boost/use-of-deprecated-hardcoded-security-protocol` queries, and these queries are now included in the security-extended suite. The `@name` metadata of these queries were also updated.
### Minor Analysis Improvements
* The "Missing return-value check for a 'scanf'-like function" query (`cpp/missing-check-scanf`) has been converted to a `path-problem` query.
* The "Potentially uninitialized local variable" query (`cpp/uninitialized-local`) has been converted to a `path-problem` query.
* Added models for `GLib` allocation and deallocation functions.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.9.5
lastReleaseVersion: 0.9.9

View File

@@ -0,0 +1,53 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Using an iterator owned by a container after the lifetime of the container has expired can lead to undefined behavior.
This is because the iterator may be invalidated when the container is destroyed, and dereferencing an invalidated iterator is undefined behavior.
These problems can be hard to spot due to C++'s complex rules for temporary object lifetimes and their extensions.
</p>
</overview>
<recommendation>
<p>
Never create an iterator to a temporary container when the iterator is expected to be used after the container's lifetime has expired.
</p>
</recommendation>
<example>
<p>
</p>
<p>
The rules for lifetime extension ensures that the code in <code>lifetime_of_temp_extended</code> is well-defined. This is because the
lifetime of the temporary container returned by <code>get_vector</code> is extended to the end of the loop. However, prior to C++23,
the lifetime extension rules do not ensure that the container returned by <code>get_vector</code> is extended in <code>lifetime_of_temp_not_extended</code>.
This is because the temporary container is not bound to a rvalue reference.
</p>
<sample src="IteratorToExpiredContainerExtendedLifetime.cpp" />
</example>
<references>
<li>CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/MEM30-C.+Do+not+access+freed+memory">MEM30-C. Do not access freed memory</a>.</li>
<li>
OWASP:
<a href="https://owasp.org/www-community/vulnerabilities/Using_freed_memory">Using freed memory</a>.
</li>
<li>
<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Lifetime.pdf">Lifetime safety: Preventing common dangling</a>
</li>
<li>
<a href="https://en.cppreference.com/w/cpp/container">Containers library</a>
</li>
<li>
<a href="https://en.cppreference.com/w/cpp/language/range-for">Range-based for loop (since C++11)</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,103 @@
/**
* @name Iterator to expired container
* @description Using an iterator owned by a container whose lifetime has expired may lead to unexpected behavior.
* @kind problem
* @precision high
* @id cpp/iterator-to-expired-container
* @problem.severity warning
* @tags reliability
* security
* external/cwe/cwe-416
* external/cwe/cwe-664
*/
// IMPORTANT: This query does not currently find anything since it relies on extractor and analysis improvements that hasn't yet been released
import cpp
import semmle.code.cpp.ir.IR
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.models.implementations.StdContainer
import semmle.code.cpp.models.implementations.StdMap
import semmle.code.cpp.models.implementations.Iterator
/**
* A configuration to track flow from a temporary variable to the qualifier of
* a destructor call
*/
module TempToDestructorConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asInstruction().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
}
predicate isSink(DataFlow::Node sink) {
sink.asOperand().(ThisArgumentOperand).getCall().getStaticCallTarget() instanceof Destructor
}
}
module TempToDestructorFlow = DataFlow::Global<TempToDestructorConfig>;
/**
* Gets a `DataFlow::Node` that represents a temporary that will be destroyed
* by a call to a destructor, or a `DataFlow::Node` that will transitively be
* destroyed by a call to a destructor.
*
* For the latter case, consider something like:
* ```
* std::vector<std::vector<int>> get_2d_vector();
* auto& v = get_2d_vector()[0];
* ```
* Given the above, this predicate returns the node corresponding
* to `get_2d_vector()[0]` since the temporary `get_2d_vector()` gets
* destroyed by a call to `std::vector<std::vector<int>>::~vector`,
* and thus the result of `get_2d_vector()[0]` is also an invalid reference.
*/
DataFlow::Node getADestroyedNode() {
exists(TempToDestructorFlow::PathNode destroyedTemp | destroyedTemp.isSource() |
result = destroyedTemp.getNode()
or
exists(CallInstruction call |
result.asInstruction() = call and
DataFlow::localFlow(destroyedTemp.getNode(),
DataFlow::operandNode(call.getThisArgumentOperand()))
|
call.getStaticCallTarget() instanceof StdSequenceContainerAt or
call.getStaticCallTarget() instanceof StdMapAt
)
)
}
predicate isSinkImpl(DataFlow::Node sink, FunctionCall fc) {
exists(CallInstruction call |
call = sink.asOperand().(ThisArgumentOperand).getCall() and
fc = call.getUnconvertedResultExpression() and
call.getStaticCallTarget() instanceof BeginOrEndFunction
)
}
/**
* Flow from any destroyed object to the qualifier of a `begin` or `end` call
*/
module DestroyedToBeginConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source = getADestroyedNode() }
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
DataFlow::FlowFeature getAFeature() {
// By blocking argument-to-parameter flow we ensure that we don't enter a
// function body where the temporary outlives anything inside the function.
// This prevents false positives in cases like:
// ```cpp
// void foo(const std::vector<int>& v) {
// for(auto x : v) { ... } // this is fine since v outlives the loop
// }
// ...
// foo(create_temporary())
// ```
result instanceof DataFlow::FeatureHasSinkCallContext
}
}
module DestroyedToBeginFlow = DataFlow::Global<DestroyedToBeginConfig>;
from DataFlow::Node source, DataFlow::Node sink, FunctionCall beginOrEnd
where DestroyedToBeginFlow::flow(source, sink) and isSinkImpl(sink, beginOrEnd)
select source, "This object is destroyed before $@ is called.", beginOrEnd, beginOrEnd.toString()

View File

@@ -0,0 +1,20 @@
#include <vector>
std::vector<int> get_vector();
void use(int);
void lifetime_of_temp_extended() {
for(auto x : get_vector()) {
use(x); // GOOD: The lifetime of the vector returned by `get_vector()` is extended until the end of the loop.
}
}
// Writes the the values of `v` to an external log and returns it unchanged.
const std::vector<int>& log_and_return_argument(const std::vector<int>& v);
void lifetime_of_temp_not_extended() {
for(auto x : log_and_return_argument(get_vector())) {
use(x); // BAD: The lifetime of the vector returned by `get_vector()` is not extended, and the behavior is undefined.
}
}

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.9.6-dev
version: 0.9.9
groups:
- cpp
- queries

View File

@@ -105,10 +105,24 @@ ConditionDecl.cpp:
# 3| getVariableAccess(): [VariableAccess] k
# 3| Type = [IntType] int
# 3| ValueCategory = prvalue(load)
# 3| getInitializingExpr(): [LTExpr] ... < ...
# 3| Type = [BoolType] bool
# 3| ValueCategory = prvalue
# 3| getLesserOperand(): [VariableAccess] j
# 3| Type = [IntType] int
# 3| ValueCategory = prvalue(load)
# 3| getGreaterOperand(): [Literal] 5
# 3| Type = [IntType] int
# 3| Value = [Literal] 5
# 3| ValueCategory = prvalue
# 3| getVariableAccess().getFullyConverted(): [CStyleCast] (bool)...
# 3| Conversion = [BoolConversion] conversion to bool
# 3| Type = [BoolType] bool
# 3| ValueCategory = prvalue
# 3| getInitializingExpr().getFullyConverted(): [CStyleCast] (int)...
# 3| Conversion = [IntegralConversion] integral conversion
# 3| Type = [IntType] int
# 3| ValueCategory = prvalue
# 3| getStmt(): [BlockStmt] { ... }
# 5| getStmt(2): [ReturnStmt] return ...
ConstructorCall.cpp:

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