Compare commits

..

329 Commits

Author SHA1 Message Date
Alex Eyers-Taylor
31a2e37418 Ruby: Compile for overlay mode. 2025-05-15 14:43:21 +01:00
Tom Hvitved
60cc63f4d4 Merge pull request #19474 from hvitved/rust/builtins-resolution
Rust: Type inference and path resolution for builtins
2025-05-15 15:22:32 +02:00
Jeroen Ketema
51229a6b48 Merge pull request #19493 from jketema/delete-expr
C++: Fix IR edge case where there are no function calls taking an argument
2025-05-15 13:31:48 +02:00
Tom Hvitved
9d37597461 Address review comments 2025-05-14 20:50:40 +02:00
Paolo Tranquilli
e4b7b914b2 Merge pull request #19334 from github/redsun82/rust-expand-attr-macros
Rust: expand attribute macros
2025-05-14 15:35:58 +02:00
Owen Mansel-Chan
8f5a2a9e29 Merge pull request #19484 from owen-mc/go/minor-fix
Go: Remove redundant code in `IR::ExtractTupleElementInstruction.getResultType()` and expand tests
2025-05-14 13:49:38 +01:00
Jeroen Ketema
401281331f C++: Fix IR edge case where there are no function calls taking an argument 2025-05-14 13:44:29 +02:00
Jeroen Ketema
96bd9a96e5 C++: Add test case for IR edge case 2025-05-14 13:36:52 +02:00
Paolo Tranquilli
c2f2522262 Merge pull request #19490 from github/redsun82/swift-type-value-expr-cfg
Swift: add new `TypeValueExpr` to CFG
2025-05-14 13:24:50 +02:00
Michael Nebel
ef4c921b5a Merge pull request #19482 from michaelnebel/csharp/code-quality-call-to-gc
C#: Add `cs/call-to-gc` to the code quality suite.
2025-05-14 13:03:24 +02:00
Paolo Tranquilli
3d38d77d63 Rust: accept dummy test output 2025-05-14 11:41:17 +02:00
Paolo Tranquilli
4709eacbf8 Swift: add change note 2025-05-14 11:37:03 +02:00
yoff
3fa563b293 Merge pull request #19483 from yoff/ruby/more-capturedExitRead
Ruby: More captured exit read nodes
2025-05-14 11:35:04 +02:00
Paolo Tranquilli
2388dd06d4 Swift: add new TypeValueExpr to CFG 2025-05-14 11:16:44 +02:00
Michael Nebel
7531a95d22 Merge pull request #19271 from michaelnebel/csharp/uncontrolled-format-string
C#: Improve precision of `cs/uncontrolled-format-string`.
2025-05-14 10:39:38 +02:00
Mathias Vorreiter Pedersen
e903d76fa0 Merge pull request #19443 from MathiasVP/generate-more-value-preserving-summaries-2
Shared: Generate more value-preserving flow summaries
2025-05-14 09:12:28 +01:00
Paolo Tranquilli
f5438390d5 Rust: enhance macro expansion testing 2025-05-14 10:01:44 +02:00
Chris Smowton
98ec3753fd Merge pull request #19489 from github/post-release-prep/codeql-cli-2.21.3
Post-release preparation for codeql-cli-2.21.3
2025-05-13 23:31:00 +01:00
github-actions[bot]
5f9dd75d7d Post-release preparation for codeql-cli-2.21.3 2025-05-13 21:49:43 +00:00
Chris Smowton
4bb829ebec Merge pull request #19488 from github/release-prep/2.21.3
Release preparation for version 2.21.3
2025-05-13 22:22:20 +01:00
github-actions[bot]
2de4a01c86 Release preparation for version 2.21.3 2025-05-13 21:14:27 +00:00
Chris Smowton
c6cc4c0e13 Merge pull request #19402 from smowton/smowton/admin/kotlin-2.2.0-support
Add support for Kotlin 2.2.0; drop Kotlin 1.5.x
2025-05-13 21:11:31 +01:00
Tom Hvitved
a02bf182c5 Rust: Type inference and path resolution for builtins 2025-05-13 21:29:32 +02:00
Tom Hvitved
9db38bcb23 Rust: Update path resolution tests 2025-05-13 21:26:50 +02:00
Chris Smowton
fecad025de Fix handling of X/jvm-default intermediate modes such as 'compatibility', the new default as of 2.2.0 2025-05-13 18:10:21 +01:00
Mathias Vorreiter Pedersen
fa7942393d Merge pull request #19477 from MathiasVP/fix-infinite-range-analysis-on-incomplete-ssa
C++: Fix infinite range analysis loop on invalid SSA
2025-05-13 16:59:11 +01:00
Paolo Tranquilli
3001d0bd1c Bazel: remove 2.0.0 rules_kotlin patching 2025-05-13 15:57:37 +01:00
yoff
3fcd46ec6c Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-13 16:57:32 +02:00
Owen Mansel-Chan
933e01b3d4 Remove redundant code
The case of a CallExpr is actually covered by the next disjunct.

Note that the CallExpr case had a subtle bug: `c.getTarget()` is not
defined when we are calling a variable. Better to use
`c.getCalleeType()`. But in this case we can just delete the code.
2025-05-13 15:55:20 +01:00
Owen Mansel-Chan
7da1ade835 Add tests for extracting tuples in f(g(...)) 2025-05-13 15:54:05 +01:00
Owen Mansel-Chan
b06491125e Expand test for Extract Tuple Instruction 2025-05-13 15:48:29 +01:00
Florin Coada
c608a9056b Merge pull request #19462 from github/changedocs/2.21.2
Update changelogs for CodeQL CLI 2.21.2
2025-05-13 15:23:35 +01:00
Paolo Tranquilli
a99556e021 Merge branch 'main' into redsun82/rust-expand-attr-macros 2025-05-13 16:21:29 +02:00
yoff
c70fd6a58c ruby: add change note 2025-05-13 16:18:33 +02:00
Tom Hvitved
d37787c4ae Rust: Add type inference tests for literals 2025-05-13 16:07:43 +02:00
Tom Hvitved
3fc9da7466 Merge pull request #19475 from hvitved/rust/literal-sub-classes
Rust: Add `LiteralExpr` sub classes
2025-05-13 16:06:53 +02:00
Asger F
169ae19015 Merge pull request #19391 from asgerf/js/typescript-path-resolution
JS: Overhaul import resolution
2025-05-13 15:46:38 +02:00
Chris Smowton
a2836f5aab Adjust integration test expectations 2025-05-13 14:42:19 +01:00
Chris Smowton
27222499d4 Update test expectation 2025-05-13 14:42:18 +01:00
Chris Smowton
fc1fd263df Fix plugin test to work with Kotlin 2.1.20 2025-05-13 14:42:17 +01:00
Chris Smowton
0d34837eaf Bump unit tests to use latest stable Kotlin 2025-05-13 14:42:16 +01:00
Chris Smowton
1afe67ab13 Accept Kotlin 2.1.20 test changes
These are mainly small changes in how source-locations are ascribed to synthetic expressions, plus three real changes:

- The comment extractor is performing better presumably due to improvements in the underlying representation
- *= /= and %= operations are once again extracted correctly; presumably their origin information has been fixed
- Reference to a static final Java field can lead to more constant propagation than before

The last one might be a minor nuisance to someone trying to find references to such a field.
2025-05-13 14:42:15 +01:00
Chris Smowton
34e0a7b23a Bump Kotlin version to keep integration test working 2025-05-13 14:42:13 +01:00
Chris Smowton
29d369f22f Don't try to decode a class from a .java file 2025-05-13 14:42:12 +01:00
Chris Smowton
0d21fa51f2 Change default version 2025-05-13 14:42:11 +01:00
Chris Smowton
3f23212d4e Update test expectation 2025-05-13 14:42:10 +01:00
Chris Smowton
2ad5e20e79 Change note 2025-05-13 14:42:09 +01:00
Chris Smowton
4cb1e7840f Update Kotlin doc table 2025-05-13 14:42:07 +01:00
Chris Smowton
a36fc30d44 Fix build for Kotlin 2.2.0 2025-05-13 14:42:06 +01:00
Chris Smowton
24feb51661 Fix Gradle config 2025-05-13 14:42:05 +01:00
Chris Smowton
163a403065 Add Kotlin 2.2.0-Beta1; drop Kotlin 1.5 2025-05-13 14:42:04 +01:00
Paolo Tranquilli
abea647bb1 Bazel: update rules_kotlin to 2.1.3 2025-05-13 14:42:03 +01:00
Chris Smowton
08aad90346 Add 2.2.0-Beta1 deps 2025-05-13 14:42:02 +01:00
Mathias Vorreiter Pedersen
f255fc2fd5 C++: Drive-by join order fix. Before:
```
Evaluated relational algebra for predicate SsaInternals::getDefImpl/1#1ed4f567@65628fbv with tuple counts:
          4935102  ~5%    {4} r1 = SCAN `SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f` OUTPUT In.2, In.3, In.0, In.1
        104274503  ~1%    {3}    | JOIN WITH `SsaInternals::DefImpl.hasIndexInBlock/2#dispred#30a6c29f_120#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.3, Lhs.2
          4921319  ~2%    {2}    | JOIN WITH `SsaInternals::DefImpl.getSourceVariable/0#dispred#72437659` ON FIRST 2 OUTPUT Lhs.2, Lhs.0
                          return r1
```
After:
```
Evaluated relational algebra for predicate SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f_1230#join_rhs@b280fb5h with tuple counts:
        4935102  ~3%    {4} r1 = SCAN `SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f` OUTPUT In.1, In.2, In.3, In.0
                        return r1

Evaluated relational algebra for predicate SsaInternals::DefImpl.hasIndexInBlock/3#dispred#31d295aa_1230#join_rhs@2be655s4 with tuple counts:
        5634706  ~1%    {4} r1 = SCAN `SsaInternals::DefImpl.hasIndexInBlock/3#dispred#31d295aa` OUTPUT In.1, In.2, In.3, In.0
                        return r1

Evaluated relational algebra for predicate SsaInternals::getDefImpl/1#1ed4f567@8afa36uu with tuple counts:
        4921319  ~2%    {2} r1 = JOIN `SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f_1230#join_rhs` WITH `SsaInternals::DefImpl.hasIndexInBlock/3#dispred#31d295aa_1230#join_rhs` ON FIRST 3 OUTPUT Lhs.3, Rhs.3
                        return r1
```
2025-05-13 14:21:28 +01:00
yoff
774b1820c2 ruby: also insert capturedExitRead-nodes by exceptional exits 2025-05-13 15:11:00 +02:00
yoff
73bae1627b ruby: test for DeadStore and captured variables 2025-05-13 15:08:01 +02:00
Tom Hvitved
ae54c62001 Simplify using non-capturing groups 2025-05-13 15:06:43 +02:00
Michael Nebel
b8f85b3f29 C#: Update integration test expected output. 2025-05-13 14:50:23 +02:00
Asger F
aea676df3c Merge pull request #19445 from asgerf/js/summaries-with-fallback
JS: Generate flow summaries from summaryModels; only generate steps as a fallback
2025-05-13 14:49:38 +02:00
Michael Nebel
f5903eaf2d C#: Add cs/call-to-gc to the code quality suite. 2025-05-13 14:46:29 +02:00
Michael Nebel
fcecc5a3af Cpp: Update model generator implementation. 2025-05-13 13:44:44 +01:00
Michael Nebel
6712cce1d7 Rust: Update model generator implementation. 2025-05-13 13:44:43 +01:00
Michael Nebel
ee83ca9125 Java: Update model generator implementation and test expected output. 2025-05-13 13:44:42 +01:00
Michael Nebel
09dc3c88b3 C#: Update model generator implementation and test expected output. 2025-05-13 13:44:40 +01:00
Michael Nebel
a94cffa27e Shared: Adjust the printing of heuristic value summaries (and fix a minor issue with output printing in captureSink). 2025-05-13 13:44:39 +01:00
Michael Nebel
6c9f248fdb Shared: Avoid generating taint based heuristic summaries when a content sensitive summary can be generated. 2025-05-13 13:44:38 +01:00
Mathias Vorreiter Pedersen
0836f0b413 C++: Cache and fix join order in 'hasIncompleteSsa'. 2025-05-13 13:41:15 +01:00
Tom Hvitved
7494eac35c Address review comments 2025-05-13 14:26:09 +02:00
Michael Nebel
3449a34018 C#: Address review comments. 2025-05-13 14:20:06 +02:00
Geoffrey White
20a012d5f1 Merge pull request #19454 from geoffw0/deref
Rust: Add Operation class
2025-05-13 13:17:14 +01:00
yoff
1c863b1bd4 Merge pull request #19476 from yoff/ruby/DeadStoreOfLocal-precision-high
ruby: adjust precision of `rb/useless-assignment-to-local`
2025-05-13 13:56:22 +02:00
Mathias Vorreiter Pedersen
c3c18bdbd2 C++: Add change note. 2025-05-13 11:28:25 +01:00
Mathias Vorreiter Pedersen
9d2eb3d9b8 C++: Filter out instructions with incomplete SSA in range analysis. 2025-05-13 10:54:22 +01:00
Mathias Vorreiter Pedersen
510df38da2 C++: Add an 'hasIncompleteSsa' predicate to check whether a function has correctly modelled SSA information. 2025-05-13 10:54:20 +01:00
Simon Friis Vindum
4cc9c24940 Merge pull request #19452 from paldepind/shared-model-generator-script
Shared: Remove the language-specific model generator scripts
2025-05-13 10:17:37 +02:00
Geoffrey White
b3dc7a21b3 Apply suggestions from code review
Co-authored-by: Simon Friis Vindum <paldepind@github.com>
2025-05-13 09:06:25 +01:00
Geoffrey White
2b6e428c37 Merge pull request #19466 from geoffw0/web
Rust: Add tests for web frameworks as taint sources
2025-05-13 09:02:46 +01:00
Simon Friis Vindum
014e7dc4bc Shared: Remove change note for internal MaD generator 2025-05-13 09:50:07 +02:00
Simon Friis Vindum
14bdc1ab22 Shared: Minor tweaks to model generator script
Co-authored-by: Michael Nebel <michaelnebel@github.com>
2025-05-13 09:31:50 +02:00
Michael Nebel
0c0e1d0c46 Merge pull request #19456 from 5idg5/5idg5-update-cs-stubs
Add new stubs definitions to System.Web
2025-05-13 08:56:06 +02:00
Sid Gawri
eb4711e884 Merge branch '5idg5-update-cs-stubs' of https://github.com/5idg5/codeql into 5idg5-update-cs-stubs 2025-05-12 17:41:32 -04:00
5idg5
6a5ce39930 Merge branch 'github:main' into 5idg5-update-cs-stubs 2025-05-12 17:39:33 -04:00
Michael Nebel
5faaa4f0f3 C#: Cleanup test options files. 2025-05-12 17:36:52 -04:00
Michael Nebel
05dc9b6d34 C#: Remove dependency to ASP.NET in the System.Web.cs stub file. 2025-05-12 17:36:10 -04:00
Michael Nebel
60d26e522e C#: Cleanup test options files. 2025-05-12 17:36:08 -04:00
Michael Nebel
82cf472f8a C#: Fix ASP tests. 2025-05-12 17:33:22 -04:00
Michael Nebel
ffd6b2677c C#: Cleanup test options files. 2025-05-12 17:33:21 -04:00
yoff
a50167812d ruby: adjust precision of rb/useless-assignment-to-local
from `medium` to `high`
2025-05-12 23:26:21 +02:00
Mathias Vorreiter Pedersen
f1b4e05579 C++: Expose 'isBusyDef'. 2025-05-12 19:45:19 +01:00
Mathias Vorreiter Pedersen
e51cb478af C++: Expose 'MemoryLocation0'. 2025-05-12 19:43:19 +01:00
Tom Hvitved
cd01bd0e07 Rust: Add LiteralExpr sub classes 2025-05-12 20:35:00 +02:00
Nicolas Will
d3282a9470 Merge pull request #19469 from nicolaswill/quantum-experimental
Add CodeQL Quantum models and queries (Java, C++) to experimental
2025-05-12 19:25:34 +02:00
Geoffrey White
a2944cdb61 Rust: Make usage of Impl more consistent with other Impl modules. 2025-05-12 16:48:06 +01:00
Geoffrey White
9160036e41 Rust: Rename OperationImpl -> Impl. 2025-05-12 16:45:41 +01:00
Geoffrey White
7c98fa87da Rust: One more bit of cleanup. 2025-05-12 16:34:08 +01:00
Geoffrey White
402a84f755 Update rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs
Co-authored-by: Simon Friis Vindum <paldepind@github.com>
2025-05-12 16:17:26 +01:00
Geoffrey White
bf8cdffffa Update rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs
Co-authored-by: Simon Friis Vindum <paldepind@github.com>
2025-05-12 16:06:33 +01:00
Geoffrey White
08fcf6114f Apply suggestions from code review
Co-authored-by: Simon Friis Vindum <paldepind@github.com>
2025-05-12 16:01:52 +01:00
Geoffrey White
6678dc490a Merge pull request #19449 from geoffw0/alloc-size-sev
Rust: Update query severities
2025-05-12 15:57:02 +01:00
Geoffrey White
a69a56122f Merge pull request #19455 from geoffw0/quality
Rust: Use the new 'quality' tag.
2025-05-12 15:56:12 +01:00
Michael Nebel
a7ddfe2e89 C#: Address review comments. 2025-05-12 16:06:02 +02:00
Michael Nebel
6cc3c820b4 C#: Add change note. 2025-05-12 15:45:03 +02:00
Michael Nebel
c96003f265 C#: Update test expected output. 2025-05-12 15:45:01 +02:00
Michael Nebel
133e8d4897 C#: Include CompositeFormat.Parse as Format like method. 2025-05-12 15:44:59 +02:00
Michael Nebel
3838a7b0d6 C#: Add a testcase for CompositeFormat.Parse for cs/uncontrolled-format-string. 2025-05-12 15:44:58 +02:00
Michael Nebel
c16be43f15 C#: Convert cs/uncontrolled-format-string tests to use test inline expectations. 2025-05-12 15:44:56 +02:00
Nicolas Will
5334e90717 Make FlowAwareElement private 2025-05-12 14:58:04 +02:00
Nicolas Will
c66ec63333 Fix query compilation errors 2025-05-12 14:48:58 +02:00
Nicolas Will
8f36624171 Add AsymmetricAlgorithmNode, refactor and address feedback 2025-05-12 14:37:44 +02:00
Nicolas Will
ab3f62eed1 Add missing tags to PrintCBOMGraph.ql queries 2025-05-12 14:34:16 +02:00
Asger F
891b2b8335 DataFlow: Support a bare Argument[n] as a valid output stack 2025-05-12 09:42:45 +02:00
Asger F
8fab235d66 DataFlow: Fix typo in a comment 2025-05-12 09:41:49 +02:00
Simon Friis Vindum
14ede4e0c5 Merge pull request #19440 from paldepind/rust-update-stdlib-models
Rust: Update generated models for core and std
2025-05-12 08:11:18 +02:00
Sid Gawri
4e3ac93f70 fix unit tests part 2 2025-05-09 16:24:42 -04:00
Sid Gawri
089ef1cae1 Merge branch 'main' of https://github.com/5idg5/codeql into 5idg5-update-cs-stubs 2025-05-09 15:35:11 -04:00
Geoffrey White
48b95f3a4e Rust: Move OperationImpl to internal/OperationImpl.qll. 2025-05-09 17:01:49 +01:00
Nicolas Will
fbf3d7c195 Update CODEOWNERS to specify shared pack directory 2025-05-09 14:36:55 +02:00
Nicolas Will
cd59ce5b04 Rename shared pack to quantum from experimental 2025-05-09 14:36:12 +02:00
Mathias Vorreiter Pedersen
64371688d7 Shared: Fix QLDoc to make QL4QL happy. 2025-05-08 10:16:09 -04:00
Nicolas Will
64e40715ee Merge branch 'quantum-experimental' of https://github.com/nicolaswill/codeql into quantum-experimental 2025-05-08 16:11:15 +02:00
Nicolas Will
c6077947a7 Update cpp and java not_included_in_qls.expected 2025-05-08 16:10:28 +02:00
Nicolas Will
d0510bc672 Merge branch 'main' into quantum-experimental 2025-05-08 04:37:37 +02:00
Nicolas Will
529128cbde Add problem.severity for java analysis queries 2025-05-08 04:20:49 +02:00
Nicolas Will
a57f4a1022 Update Java analysis query metadata 2025-05-08 04:13:57 +02:00
Nicolas Will
e03f57da9b Update type name in experimental BrokenCrypto.ql 2025-05-08 04:03:10 +02:00
Nicolas Will
b8c3b43cc4 Fix KnownAsymmetricAlgorithm query id 2025-05-08 03:58:06 +02:00
Nicolas Will
b558e844ff Update slice query metadata and output tables 2025-05-08 03:56:20 +02:00
Nicolas Will
986c8e1aec Change Java inventory slices to @kind table 2025-05-08 03:24:04 +02:00
Nicolas Will
0c6e124b01 Delete development test query 2025-05-08 03:02:59 +02:00
Nicolas Will
1135fbe950 Fix EVP_Hash_Initializer typo 2025-05-08 02:58:43 +02:00
Nicolas Will
1d8a57e7da Fix EVP Cipher class, predicate, and comment typos 2025-05-08 02:56:52 +02:00
Nicolas Will
e956d041dc Format LibraryDetector.qll 2025-05-08 02:51:53 +02:00
Nicolas Will
a7ebe4a51a Fix typo in asymmetric inventory slice query id 2025-05-08 02:43:29 +02:00
Nicolas Will
0066f74d3f Delete development scripts 2025-05-08 02:40:56 +02:00
Nicolas Will
7339dd0077 Rename "Quantum" to "quantum" in dir structure 2025-05-08 02:39:40 +02:00
Nicolas Will
ac72abd3a6 Refactor directory structure (shared experimental) 2025-05-08 02:35:09 +02:00
Nicolas Will
c19291be88 Refactor 'cryptography' and 'Quantum' to 'quantum' 2025-05-08 01:38:53 +02:00
Nicolas Will
314f1ff93f Refactor Java directory structure 2025-05-08 00:28:32 +02:00
Nicolas Will
56670c66f1 Revert Python changes and delete implementation 2025-05-08 00:26:13 +02:00
Nicolas Will
f5a36566d1 Merge pull request #11 from nicolaswill/brodes/openssl_refactor
Brodes/openssl refactor
2025-05-07 23:10:53 +02:00
Geoffrey White
19f86fd67f Rust: Address confusing / typo'd paths. 2025-05-07 10:46:16 +01:00
Geoffrey White
49ff967465 Rust: Add a dataflow sources test for the Axum web fraemework. 2025-05-07 10:17:58 +01:00
Geoffrey White
e56519d959 Rust: Add a dataflow sources test for the Actix web fraemework. 2025-05-07 10:17:57 +01:00
Geoffrey White
310c02f1fb Rust: Add a dataflow sources test for the Poem web fraemework. 2025-05-07 10:17:56 +01:00
Owen Mansel-Chan
a857069345 Merge pull request #19464 from owen-mc/go/fix/extract-recv-alias-type
Go: fix database inconsistency when receiver has alias type
2025-05-06 15:08:42 -04:00
Owen Mansel-Chan
c781f98bdc (unrelated tidy up) resolveTypeAlias not needed
`types.Unalias` already does the same thing
2025-05-06 05:45:06 -04:00
Owen Mansel-Chan
228c45aaf8 Look through aliases when identifying method receivers 2025-05-06 05:45:04 -04:00
Sid Gawri
7231f53b6e revert system.net stubs 2025-05-05 21:59:37 -04:00
Sid Gawri
0691cd3e9a Merge branch 'main' of https://github.com/5idg5/codeql into 5idg5-update-cs-stubs 2025-05-05 21:55:29 -04:00
Florin Coada
1533d7a4cc Update codeql-cli-2.21.2.rst 2025-05-05 11:30:15 -04:00
Florin Coada
c7026c03df Update changelogs for CodeQL CLI 2.21.2 and adjust query reporting for unversioned immutable actions 2025-05-05 11:13:42 -04:00
Sid Gawri
d600eb42cf add new stubs 2025-05-02 17:25:02 -04:00
REDMOND\brodes
4042081539 Missing files, should have been part of last commit. 2025-05-02 16:35:27 -04:00
REDMOND\brodes
0a0be41527 Intermediate progress towards getting hashing upgraded. Still need to handle the final and update mechanics, matching the JCA. Similarly need to update cipher to follow the JCA for update/final as well. 2025-05-02 16:33:52 -04:00
REDMOND\brodes
94632931ba Clean up 2025-05-02 14:11:10 -04:00
REDMOND\brodes
09d473674b Working refactor for cipher, padding, block mode. Still haven't completed connecting padding to algorithm instances if through a set padding interface. 2025-05-02 14:10:38 -04:00
REDMOND\brodes
7481de75cb Updating the model to infer implicit cipher key sizes. 2025-05-02 14:07:38 -04:00
REDMOND\brodes
c08525ad81 Additional cleanup 2025-05-02 14:07:13 -04:00
REDMOND\brodes
5694f029de Misc. cleanup 2025-05-02 14:03:50 -04:00
Geoffrey White
f59ef58c1f Rust: Update query suite list. 2025-05-02 17:47:48 +01:00
Geoffrey White
16ed8476ce Rust: Use the new 'quality' tag. 2025-05-02 17:24:13 +01:00
Geoffrey White
566b3dd8d9 Rust: Update code scanning queries list. 2025-05-02 17:13:14 +01:00
Geoffrey White
d0287e9496 Merge branch 'main' into alloc-size-sev 2025-05-02 17:08:05 +01:00
Geoffrey White
09dc7fc5c4 Rust: Autoformat. 2025-05-02 16:58:43 +01:00
Mathias Vorreiter Pedersen
bce5f2539f C++/C#/Java/Rust: Fixup tests. 2025-05-02 16:52:05 +01:00
Mathias Vorreiter Pedersen
37bc2bf5b3 Shared: Deduplicate flow summaries. 2025-05-02 16:51:15 +01:00
Geoffrey White
dc1b4fcf7a Rust: Unify getOperatorName() methods into Operation. 2025-05-02 16:46:51 +01:00
Geoffrey White
be2017621f Rust: Unify getAnOperand() methods into Operation. 2025-05-02 16:46:50 +01:00
Geoffrey White
060d5152c4 Rust: Add an Operation class above LogicalOperation, AssignmentOperation etc. 2025-05-02 16:46:44 +01:00
Paolo Tranquilli
674800748b Rust: fix location emission 2025-05-02 15:24:31 +02:00
Mathias Vorreiter Pedersen
4d2f2b89e7 Shared/Java/C#/Rust/C++: Rename 'captureHeuristicFlow' to 'captureFlow'. 2025-05-02 14:02:41 +01:00
Mathias Vorreiter Pedersen
54f0eed2c6 Shared: Rename 'asLiftedTaintModel' to 'asLiftedModel'. 2025-05-02 13:54:58 +01:00
Paolo Tranquilli
557f468fc0 Merge branch 'main' into redsun82/rust-expand-attr-macros 2025-05-02 13:43:17 +02:00
Paolo Tranquilli
82736ea621 Rust: add diagnostics about item expansion not working properly 2025-05-02 13:43:00 +02:00
Asger F
1f308ee47a JS: Explain use of monotonicAggregates 2025-05-02 13:22:27 +02:00
Asger F
5c9218fe5a JS: Add comment about 'path' heuristic 2025-05-02 13:22:25 +02:00
Simon Friis Vindum
c6d95ceeb0 Shared: Remove the language-specific model generator scripts 2025-05-02 13:21:10 +02:00
Simon Friis Vindum
3aed1c8696 Merge branch 'main' into rust-update-stdlib-models 2025-05-02 12:54:43 +02:00
Asger F
f3e0cfd947 Apply suggestions from code review
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2025-05-02 12:41:29 +02:00
Geoffrey White
f64e86fe2e Rust: Add a library test for Operations. 2025-05-02 11:22:48 +01:00
Mathias Vorreiter Pedersen
d5bc95daeb Merge branch 'main' into generate-more-value-preserving-summaries-2 2025-05-02 10:51:11 +01:00
Asger F
16fc8c3d9e JS: Benign test updates 2025-05-02 11:09:19 +02:00
Geoffrey White
93f8cea884 Rust: Add + clean up some QLDoc. 2025-05-01 17:11:34 +01:00
Geoffrey White
c9ce6c0fb6 Rust: Demote rust/cleartext-logging to warning. 2025-05-01 16:42:41 +01:00
Geoffrey White
bd3155ef0c Rust: Promote rust/uncontrolled-allocation-size to warning. 2025-05-01 16:42:13 +01:00
Asger F
a44bdf3be2 JS: Generate summaries from summaryModel, and only generate steps as a fallback 2025-05-01 15:22:47 +02:00
Asger F
0fc1ae272e DataFlow: expose from FlowSummaries whether a summary is supported 2025-05-01 15:22:12 +02:00
Asger F
ca5f8b0c1d JS: Move some code into ModelsAsData.qll 2025-05-01 15:17:07 +02:00
Simon Friis Vindum
499d224c2b Rust: Update generated models for core and std 2025-05-01 10:54:05 +02:00
Mathias Vorreiter Pedersen
d8eafbb9e2 C++: Fixup queries and accept test changes. 2025-04-30 20:34:35 +01:00
Mathias Vorreiter Pedersen
775197372c Rust: Fixup queries. 2025-04-30 20:34:33 +01:00
Mathias Vorreiter Pedersen
07641e48ab Java: Fixup queries and accept test changes. 2025-04-30 20:34:32 +01:00
Mathias Vorreiter Pedersen
cd47379700 C#: Fixup queries and accept test changes. 2025-04-30 20:34:30 +01:00
Mathias Vorreiter Pedersen
607a1e46da Shared: Generate value-preserving summaries when possible. 2025-04-30 20:34:27 +01:00
REDMOND\brodes
c80588cda1 Adding content to KnownSymmetricCipherAlgorithmql. 2025-04-30 11:41:28 -04:00
Nicolas Will
83617e099f Merge pull request #2 from nicolaswill/knewbury01/JCA-sample
Implement first stage cryptography modelling and queries
2025-04-30 16:39:56 +02:00
Paolo Tranquilli
6ecaf65132 Rust: fix downgrade script 2025-04-30 16:38:13 +02:00
Nicolas Will
27c7bf3047 Merge branch 'github:main' into crypto-test 2025-04-30 16:35:26 +02:00
Nicolas Will
2b1b90ccc4 Merge pull request #4 from nicolaswill/brodes/cipher_operation
Adding a sketch for a CipherOperation concept to model encryption/dec…
2025-04-30 16:32:20 +02:00
Nicolas Will
dd2f53f42e Merge pull request #10 from nicolaswill/brodes/key_agreement
Initial progress on key agreement.
2025-04-30 16:31:42 +02:00
Nicolas Will
9c87ad8293 Merge branch 'brodes/key_agreement' of https://github.com/nicolaswill/codeql into brodes/key_agreement 2025-04-30 16:28:35 +02:00
Nicolas Will
7f24a2557d Add modelling for JCA key gen cipher algorithm 2025-04-30 16:28:31 +02:00
Paolo Tranquilli
8ffe4d6593 Merge branch 'main' into redsun82/rust-expand-attr-macros 2025-04-30 15:25:32 +02:00
Paolo Tranquilli
ecd80fbc34 Rust: fix QL compilation errors 2025-04-30 15:25:01 +02:00
Paolo Tranquilli
a7a887c828 Rust: separate attribute macro and macro call expansions 2025-04-29 16:18:40 +02:00
Asger F
b0f73f1cbd JS: Update test output now that we import .d.ts files more liberally 2025-04-29 16:06:39 +02:00
Asger F
70a5ec5607 JS: Add package.json files in tests relying on node_modules
We don't extract node_modules folders by default so these tests aren't
that relevant anymore, and we no longer follow node_modules resolution
rules directly.

Instead, these imports are resolved based on the monorepo support which
simply requires a package.json file to exist. There is not a good enough
reason to support node_modules directly, so we're accepting some
minor regression in these tests.
2025-04-29 16:06:38 +02:00
Asger F
5de2c938d8 JS: Rename getTargetFile to getImportedFile and remove its deprecated name clash
'getTargetFile' was originally named to avoid the clash with 'getImportedFile' from a subclass. But we now just merge the two predicates.
2025-04-29 16:06:36 +02:00
Asger F
be5de9c080 JS: Update test output
path.resolve() and template expressions are now working.

Previously they could not be resolved because Import.getImportedPath() returned a PathExpr,
and these were not instances of PathExpr.
2025-04-29 16:06:35 +02:00
Asger F
ed2a832a55 JS: Deprecate PathExpr and related classes 2025-04-29 13:23:47 +02:00
Asger F
fe055ad603 JS: Use PackageJsonEx instead of resolveMainModule 2025-04-29 13:23:45 +02:00
Asger F
c293f03b9e JS: Remove a dependency on getImportedPath()
To avoid negative recursion in some upcoming changes, we want to make sure the modeling of createRequire does not depend on getImportedPath().
2025-04-29 13:23:43 +02:00
Asger F
a195d074c9 JS: Resolve Angular2 templateUrl with ResolveExpr instead of PathExpr 2025-04-29 13:23:42 +02:00
Asger F
d724874969 JS: Implement babel-plugin-root-import as a PathMapping 2025-04-29 13:23:40 +02:00
Asger F
e4420f63fb JS: Move babel-root-import test
This moves the test for the babel `root-import` plugin into the new
unit test for import resolution, so we only have one set of tests to
maintain.

The actual implementation is added in the next commit.
2025-04-29 13:23:38 +02:00
Asger F
6725cb5b8c JS: Implement import resolution 2025-04-29 13:23:37 +02:00
Asger F
ed4864edf7 JS: Add two more helpers to FilePath class 2025-04-29 13:07:21 +02:00
Asger F
f542956f66 JS: Add internal extension of PackageJson class 2025-04-29 13:07:19 +02:00
Asger F
bb91df8145 JS: Add helper for doing path resolution with JS rules 2025-04-29 13:07:18 +02:00
Asger F
59e1cbcc7b JS: Add tsconfig class 2025-04-29 13:07:16 +02:00
Asger F
ef32a036b1 JS: Extract from methods from PathString into a non-abstract base class
The new class 'FilePath' has bindingset[this] so one just has to cast a string to that type and you can use its methods.
2025-04-29 13:07:15 +02:00
Asger F
17aa5220a6 JS: Add some helpers 2025-04-29 13:07:14 +02:00
Asger F
565cb434fc JS: Add test 2025-04-29 13:07:10 +02:00
Asger F
359525b65a JS: Extract more tsconfig.json patterns 2025-04-29 12:46:49 +02:00
Asger F
8c0b0c4800 JS: Ensure json files are extracted properly in tests 2025-04-29 12:46:20 +02:00
Asger F
ec9d15bb79 JS: Make shared Folder module visible 2025-04-29 09:42:25 +02:00
Asger F
2ce01bfb9a Add Folder::Resolve as a generalisation of Folder::Append 2025-04-29 09:42:23 +02:00
Asger F
eb059969e3 Move getAChildContainer one scope up 2025-04-29 09:42:22 +02:00
REDMOND\brodes
ac798f2bc6 Cipher Algorithm Slices 2025-04-28 16:03:41 -04:00
REDMOND\brodes
ac3675bdac Typo fix 2025-04-28 16:00:41 -04:00
REDMOND\brodes
219476cee0 Adding KDF iteration count inventory filters. 2025-04-28 15:47:58 -04:00
REDMOND\brodes
ce3eabf05a Updating model to support slicing. 2025-04-28 14:56:28 -04:00
REDMOND\brodes
5a8bffac11 Removing old asymmetric algorithm slice 2025-04-28 14:56:08 -04:00
REDMOND\brodes
1fd7643ab3 Adding example slicing queries. 2025-04-28 14:54:38 -04:00
REDMOND\brodes
7b7ed61beb Adding an asymmetric algorithm slice. 2025-04-28 11:34:32 -04:00
REDMOND\brodes
fdd09a4dbf Adding a new means for determining if there is nonce reuse. 2025-04-28 11:34:16 -04:00
REDMOND\brodes
28ccc83346 Adding a means to distinguish asymmetric algorithms. 2025-04-28 11:33:37 -04:00
Paolo Tranquilli
2d32c366d8 Rust: add missing expected files 2025-04-28 10:46:36 +02:00
Paolo Tranquilli
adeaceb7af Rust: accept test changes 2025-04-25 17:41:13 +02:00
Paolo Tranquilli
49cf1739a4 Rust: expand attribute macros 2025-04-25 16:16:49 +02:00
Nicolas Will
1958c192ec Reimplement EC, MAC, key creation logic + consumer 2025-04-15 23:00:12 -04:00
Nicolas Will
b9d0abda63 Move CipherOperation into KeyOperation, refactor
- KeyOperation and Algorithm now encompasses encryption, decryption, wrapping, unwrapping, signing, and verifying.
- Removed elliptic curve implementation from JCA.qll pending rewrite
- Removed JCAAlgorithmInstance abstraction from JCA.qll
- Cleaned up and removed JCA-specific naming from Model.qll
- Added and clarified documentation
2025-04-09 21:19:00 +02:00
REDMOND\brodes
a2fe19af38 Initial progress on key agreement. 2025-04-04 16:00:05 -04:00
Ben Rodes
69429a3e02 Merge pull request #9 from nicolaswill/brodes/elliptic_curves
Misc. modifications to support elliptic curves and hooking them up to…
2025-04-04 09:06:20 -04:00
REDMOND\brodes
697c9f0bb0 Elliptic curve AVCs are incorrect, but I'm not sure how to fix them generally. Putting in a stop gap to use 'isCipherAVC' for now. 2025-04-04 09:02:09 -04:00
REDMOND\brodes
66a60296b8 Merge branch 'brodes/cipher_operation' into brodes/elliptic_curves 2025-04-02 13:46:12 -04:00
Nicolas Will
50507586ac Refactor output artifact type 2025-04-02 19:44:57 +02:00
REDMOND\brodes
ac96649a02 Misc. modifications to support elliptic curves and hooking them up to keygeneration. 2025-04-01 16:15:49 -04:00
Nicolas Will
bec69ca106 Refactor consumer and generic source model 2025-03-26 13:27:32 +01:00
Nicolas Will
9cd0340d21 Remove rankdir=LR; from DOT output 2025-03-26 13:26:45 +01:00
Nicolas Will
e9c3e14fab Merge branch 'brodes/cipher_operation' of https://github.com/nicolaswill/codeql into brodes/cipher_operation 2025-03-22 08:01:06 +01:00
Nicolas Will
fb7c003398 Add initial MAC support for JCA, refactor hashes 2025-03-22 08:01:03 +01:00
REDMOND\brodes
9278a41578 Merge branch 'brodes/cipher_operation' of https://github.com/nicolaswill/codeql into brodes/cipher_operation 2025-03-20 16:28:43 -04:00
REDMOND\brodes
b695641362 Add signature to cipher operation 2025-03-20 16:27:20 -04:00
Nicolas Will
d18dac0c8e Add JCA key (generation) modelling 2025-03-20 21:26:18 +01:00
REDMOND\brodes
63aaebbea6 . 2025-03-19 18:30:06 -04:00
Nicolas Will
95607c5f31 Refactor instances and consumers + add JCA hashes 2025-03-18 22:05:00 +01:00
REDMOND\brodes
8a7671dc2a Adding block mode models to openssl. 2025-03-11 15:20:05 -04:00
REDMOND\brodes
71eae39feb Adding missing block modes. 2025-03-11 15:19:42 -04:00
REDMOND\brodes
c98e6d7c56 Adding a stub EVP_CIpher_Operation for EVP_PKEY, this probably should be made into it's own class, hence it is a stub with comments. 2025-03-11 14:49:07 -04:00
REDMOND\brodes
a9458ba762 Formatting, removing dead comments, 2025-03-11 14:48:38 -04:00
REDMOND\brodes
d988afd4a4 Adding an EVP_AASYM_CIPHER_fetch getter. 2025-03-11 14:47:10 -04:00
REDMOND\brodes
7757279908 Adding a KDF algorithm getter. 2025-03-11 14:46:36 -04:00
REDMOND\brodes
44b1e921d6 commenting out hash size for now, TODO 2025-03-11 14:10:04 -04:00
REDMOND\brodes
085e8d40fd Hash nodes have instances. 2025-03-11 14:06:36 -04:00
REDMOND\brodes
f69b057893 Updating OpenSSLKnownAlgorithmConstants.qll (a few bugs) and also enforcing that known key sizes are on the normalized name (need to re-visit for GOST). 2025-03-11 13:35:44 -04:00
REDMOND\brodes
ae574f7cf2 Resolving hash and cipher types for openssl not using literals but KnownOpenSSLAlgorithmConstant. 2025-03-11 13:35:02 -04:00
REDMOND\brodes
f72efa638a Uncommenting out generic dataflow 2025-03-10 16:12:53 -04:00
REDMOND\brodes
c83cb533ce Adding an instantiation of the additional flow step class to automatically apply to generic dataflow. Flow step passthrough comes from the algorithm to getter flow passthroughs. 2025-03-10 15:56:01 -04:00
REDMOND\brodes
036035b6a2 Adding modeling for OpenSSL random number generation. 2025-03-10 15:04:19 -04:00
REDMOND\brodes
fe52351aed Stubbing out hash operation node, borrowing from cipher operaiton node 2025-03-10 14:10:55 -04:00
REDMOND\brodes
73368ea59a Adding hashes to openssl library import 2025-03-10 13:27:39 -04:00
REDMOND\brodes
0672027822 Tracing new notion of known getters, which now includes direct getters for cipher and hash. Removed a redundant hash qll, and fixed misplacement of has type in model. 2025-03-10 11:46:26 -04:00
REDMOND\brodes
451808616e Getting rid of commented out code. 2025-03-10 11:35:16 -04:00
REDMOND\brodes
bd07b8a4c7 Making getter flow through 'copy' more general (copy can appear in any part of the call name now. 2025-03-10 11:34:26 -04:00
REDMOND\brodes
6a4659fc7e Updating known constants for OpenSSL to handle direct algorithm getters from older versions of openssl (e.g., EVP_md5()) 2025-03-10 11:33:46 -04:00
REDMOND\brodes
3316d6135d Ctx flow comments. 2025-03-10 11:32:14 -04:00
REDMOND\brodes
d99812a10d Adding GOSTHash to THashType. 2025-03-10 09:59:28 -04:00
REDMOND\brodes
64241caf1d Merge branch 'brodes/cipher_operation' of https://github.com/nicolaswill/codeql into brodes/cipher_operation 2025-03-07 14:25:13 -05:00
REDMOND\brodes
bac0a635f9 Initial hash models for openssl. 2025-03-07 14:24:01 -05:00
Nicolas Will
47affa0fed Restore location output for nodes 2025-03-07 18:30:58 +01:00
REDMOND\brodes
cf72fde911 Fixing cross product in getPropertyAsGraphString (parameter root not bound in all cases, fixing using a bindingetset) 2025-03-07 12:11:12 -05:00
REDMOND\brodes
32d29ffde3 Changed casing on TCipherType, Added some initial fixes for hash support, started developing openssl hashing modeling. 2025-03-07 10:02:36 -05:00
REDMOND\brodes
b9bd199432 Regression fixes for JCA 2025-03-06 13:39:23 -05:00
REDMOND\brodes
6083df2b7f Completed tying algorithm instances to consumers. Now the model should have known literals for cipher instances, and it traces those instances to consumers (inits) and those inits are traced to cipher operations. 2025-03-05 15:48:08 -05:00
REDMOND\brodes
de3ff45cba Misc updates for OpenSSL modeling to trace algorithm literals to known alg getters, and converting the literal to a TCipherType. 2025-03-05 15:17:52 -05:00
REDMOND\brodes
cce5f24b38 Initial OpenSSL modeling work. 2025-03-04 15:52:57 -05:00
REDMOND\brodes
8865d89fe9 Removing old ReusedNonce query. 2025-03-03 16:51:30 -05:00
REDMOND\brodes
2ee1681126 Adding a proof-of-concept PossibleReusedNonce query. 2025-03-03 15:09:27 -05:00
REDMOND\brodes
14cb2bb12f Updates to insecure or unknown nonce at operation. 2025-03-03 14:42:50 -05:00
REDMOND\brodes
076f53147d Proof-of-concept query for InsecureOrUnknownNonceAtOperation 2025-03-03 13:53:16 -05:00
Nicolas Will
627790f98b Clean up consumer and instance interfaces 2025-03-03 19:06:53 +01:00
Nicolas Will
cf33cf7653 Add input and output nodes and fix cross product 2025-02-28 15:21:46 +01:00
Nicolas Will
0354afc365 Make ArtifactConsumers instances of some Artifacts
TODO: refactor the interfaces
2025-02-27 15:54:38 +01:00
Nicolas Will
ef0614ad45 Restore removed node location output 2025-02-27 05:45:27 +01:00
Nicolas Will
04f4683399 Rewrite handling of known unknowns and data-flow 2025-02-27 05:42:02 +01:00
Nicolas Will
f55f27b0d9 Expand handling of generic artifact sources 2025-02-25 18:22:38 +01:00
Nicolas Will
eb91ecf1fb Add generic artifact data-flow
The relation between RNG and other artifacts has been added
Nonce has been completed to report its source
2025-02-25 02:53:13 +01:00
Nicolas Will
2b0b927b0b Add Nonce association to Operation, update graph 2025-02-24 17:37:41 +01:00
REDMOND\brodes
86cab46b8d Misc. updates to support all JCA cipher operations, including wrap, unwrap and doFinal calls. Corrected pathing for init tracing to detect what mode is being set along a path. Added support for tracing the init operation mode argument to source. Since this involved creating an Operation Mode, changes were also made to make cipher block modes (CBC) more explicit (previously just called mode, but now that term is used for various purposes). 2025-02-21 12:53:35 -05:00
REDMOND\brodes
9ac9252f75 Adding a todo 2025-02-20 11:11:41 -05:00
REDMOND\brodes
011ed3fbfd Simplifying additional flow step logic. 2025-02-20 11:10:24 -05:00
REDMOND\brodes
83dc5b9906 Fixing type bug 2025-02-20 10:45:33 -05:00
REDMOND\brodes
9ee4a7a7b8 Adding a sketch for a CipherOperation concept to model encryption/decryption operations. 2025-02-20 10:37:40 -05:00
REDMOND\brodes
3871c6a33e Adding support for encryption operation detection. 2025-02-18 16:09:00 -05:00
Nicolas Will
8707e4d9a3 Continue Artifact data-flow WIP 2025-02-18 18:35:49 +01:00
Nicolas Will
df01fa7a9c Expand model and JCA modeling 2025-02-17 00:16:08 +01:00
Nicolas Will
b777a22d35 Expand model and specialize newtype relations 2025-02-14 23:43:07 +01:00
Nicolas Will
874e3b5e06 Modify model to use newtypes, expand modeling 2025-02-12 17:58:15 +01:00
Nicolas Will
4d44755945 Refactor Model and CBOM print queries 2025-02-11 15:37:15 +01:00
Kristen Newbury
1a12fb3099 Update JCA model, refactor modes 2025-02-10 13:49:32 -05:00
Kristen Newbury
59208bdb85 Update JCA model to use shared lib 2025-02-10 12:22:22 -05:00
Kristen Newbury
9c8ade7ddd Merge branch 'nic/crypto-test' into knewbury01/JCA-sample 2025-02-10 11:48:15 -05:00
Kristen Newbury
6005437001 Update JCA model with flow to call as AESuse and format JCA model 2025-02-10 11:26:48 -05:00
Kristen Newbury
60d931af9f Update progress on JCA 2025-02-07 15:46:13 -05:00
Nicolas Will
7a96f5682e Merge pull request #3 from nicolaswill/nicolaswill/shared-crypto-library
Move language-agnostic model to shared library
2025-02-06 21:57:10 +01:00
Nicolas Will
3dc28c2d17 Move language-agnostic model to shared library 2025-02-06 21:54:18 +01:00
Kristen Newbury
2e12bb5f5c Merge branch 'nic/crypto-test' into knewbury01/JCA-sample 2025-02-06 12:56:32 -05:00
Nicolas Will
cd70acde66 Merge pull request #1 from nicolaswill/brodes/experiments
Concepts for elliptic curves and misc. updates.
2025-02-06 14:43:09 +01:00
Kristen Newbury
efcf7eab0c Add broken crypto query 2025-02-05 17:24:25 -05:00
Kristen Newbury
86e51dad8a Improve JCA aes alg model, add test 2025-02-05 13:39:48 -05:00
Kristen Newbury
5f355c7f55 Add first sample JCA encryption model 2025-02-04 11:55:09 -05:00
Nicolas Will
69a63855cc Update CBOMGraph.ql 2025-01-29 21:55:57 +01:00
Nicolas Will
9af18bc100 WIP: add dgml/dot output/remove test code 2025-01-29 19:45:04 +01:00
REDMOND\brodes
0cd3df9d26 Concepts for elliptic cureve and misc. updates. 2025-01-29 10:27:46 -05:00
Nicolas Will
e027b0e9a0 WIP: add properties 2025-01-28 02:02:06 +01:00
Nicolas Will
78362341ff WIP: hash types example and documentation 2025-01-24 22:32:32 +01:00
Nicolas Will
1a7d8cb99d WIP 2025-01-24 17:33:03 +01:00
Nicolas Will
395d54bf86 Create Base.qll 2025-01-23 12:46:09 +01:00
721 changed files with 33808 additions and 4595 deletions

View File

@@ -68,7 +68,7 @@ jobs:
DATABASE=$2
cd codeql-$QL_VARIANT
SHORTNAME=`basename $DATABASE`
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT
python misc/scripts/models-as-data/generate_mad.py --language java --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT
mkdir -p $MODELS/$SHORTNAME
mv java/ql/lib/ext/generated/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME
cd ..

View File

@@ -17,6 +17,7 @@
# Experimental CodeQL cryptography
**/experimental/quantum/ @github/ps-codeql
/shared/quantum/ @github/ps-codeql
# CodeQL tools and associated docs
/docs/codeql/codeql-cli/ @github/codeql-cli-reviewers

View File

@@ -24,7 +24,7 @@ bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1")
bazel_dep(name = "gazelle", version = "0.40.0")
bazel_dep(name = "rules_dotnet", version = "0.17.4")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
@@ -193,10 +193,6 @@ use_repo(
kotlin_extractor_deps,
"codeql_kotlin_defaults",
"codeql_kotlin_embeddable",
"kotlin-compiler-1.5.0",
"kotlin-compiler-1.5.10",
"kotlin-compiler-1.5.20",
"kotlin-compiler-1.5.30",
"kotlin-compiler-1.6.0",
"kotlin-compiler-1.6.20",
"kotlin-compiler-1.7.0",
@@ -208,10 +204,7 @@ use_repo(
"kotlin-compiler-2.0.20-Beta2",
"kotlin-compiler-2.1.0-Beta1",
"kotlin-compiler-2.1.20-Beta1",
"kotlin-compiler-embeddable-1.5.0",
"kotlin-compiler-embeddable-1.5.10",
"kotlin-compiler-embeddable-1.5.20",
"kotlin-compiler-embeddable-1.5.30",
"kotlin-compiler-2.2.0-Beta1",
"kotlin-compiler-embeddable-1.6.0",
"kotlin-compiler-embeddable-1.6.20",
"kotlin-compiler-embeddable-1.7.0",
@@ -223,10 +216,7 @@ use_repo(
"kotlin-compiler-embeddable-2.0.20-Beta2",
"kotlin-compiler-embeddable-2.1.0-Beta1",
"kotlin-compiler-embeddable-2.1.20-Beta1",
"kotlin-stdlib-1.5.0",
"kotlin-stdlib-1.5.10",
"kotlin-stdlib-1.5.20",
"kotlin-stdlib-1.5.30",
"kotlin-compiler-embeddable-2.2.0-Beta1",
"kotlin-stdlib-1.6.0",
"kotlin-stdlib-1.6.20",
"kotlin-stdlib-1.7.0",
@@ -238,6 +228,7 @@ use_repo(
"kotlin-stdlib-2.0.20-Beta2",
"kotlin-stdlib-2.1.0-Beta1",
"kotlin-stdlib-2.1.20-Beta1",
"kotlin-stdlib-2.2.0-Beta1",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -1,3 +1,7 @@
## 0.4.9
No user-facing changes.
## 0.4.8
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.8
lastReleaseVersion: 0.4.9

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.9-dev
version: 0.4.10-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,3 +1,7 @@
## 0.6.1
No user-facing changes.
## 0.6.0
### Breaking Changes

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.0
lastReleaseVersion: 0.6.1

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.1-dev
version: 0.6.2-dev
library: false
warnOnImplicitThis: true
groups: [actions, queries]

View File

@@ -299,6 +299,7 @@ ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SigningAlgorithms.q
ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SymmetricEncryptionAlgorithms.ql
ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SymmetricPaddingAlgorithms.ql
ql/cpp/ql/src/experimental/cryptography/inventory/new_models/UnknownAsymmetricKeyGeneration.ql
ql/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql
ql/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql
ql/cpp/ql/src/external/examples/filters/EditDefectMessage.ql
ql/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql

View File

@@ -1,3 +1,9 @@
## 4.3.1
### Bug Fixes
* Fixed an infinite loop in `semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies.
## 4.3.0
### New Features

View File

@@ -0,0 +1,5 @@
## 4.3.1
### Bug Fixes
* Fixed an infinite loop in `semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 4.3.0
lastReleaseVersion: 4.3.1

View File

@@ -0,0 +1,113 @@
private import cpp as Language
import semmle.code.cpp.dataflow.new.DataFlow
import codeql.quantum.experimental.Model
module CryptoInput implements InputSig<Language::Location> {
class DataFlowNode = DataFlow::Node;
class LocatableElement = Language::Locatable;
class UnknownLocation = Language::UnknownDefaultLocation;
LocatableElement dfn_to_element(DataFlow::Node node) {
result = node.asExpr() or
result = node.asParameter() or
result = node.asVariable()
}
string locationToFileBaseNameAndLineNumberString(Location location) {
result = location.getFile().getBaseName() + ":" + location.getStartLine()
}
predicate artifactOutputFlowsToGenericInput(
DataFlow::Node artifactOutput, DataFlow::Node otherInput
) {
ArtifactFlow::flow(artifactOutput, otherInput)
}
}
module Crypto = CryptographyBase<Language::Location, CryptoInput>;
module ArtifactFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
}
predicate isSink(DataFlow::Node sink) {
sink = any(Crypto::FlowAwareElement other).getInputNode()
}
predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}
module ArtifactFlow = DataFlow::Global<ArtifactFlowConfig>;
/**
* Artifact output to node input configuration
*/
abstract class AdditionalFlowInputStep extends DataFlow::Node {
abstract DataFlow::Node getOutput();
final DataFlow::Node getInput() { result = this }
}
/**
* Generic data source to node input configuration
*/
module GenericDataSourceFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::GenericSourceInstance i).getOutputNode()
}
predicate isSink(DataFlow::Node sink) {
sink = any(Crypto::FlowAwareElement other).getInputNode()
}
predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}
module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
}
predicate isSink(DataFlow::Node sink) {
sink = any(Crypto::FlowAwareElement other).getInputNode()
}
predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}
module ArtifactUniversalFlow = DataFlow::Global<ArtifactUniversalFlowConfig>;
import OpenSSL.OpenSSL

View File

@@ -0,0 +1,170 @@
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
/**
* Traces 'known algorithms' to AVCs, specifically
* algorithms that are in the set of known algorithm constants.
* Padding-specific consumers exist that have their own values that
* overlap with the known algorithm constants.
* Padding consumers (specific padding consumers) are excluded from the set of sinks.
*/
module KnownOpenSSLAlgorithmToAlgorithmValueConsumerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof KnownOpenSSLAlgorithmConstant
}
predicate isSink(DataFlow::Node sink) {
exists(OpenSSLAlgorithmValueConsumer c |
c.getInputNode() = sink and
not c instanceof PaddingAlgorithmValueConsumer
)
}
predicate isBarrier(DataFlow::Node node) {
// False positive reducer, don't flow out through argv
exists(VariableAccess va, Variable v |
v.getAnAccess() = va and va = node.asExpr()
or
va = node.asIndirectExpr()
|
v.getName().matches("%argv")
)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
knownPassThroughStep(node1, node2)
}
}
module KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow =
DataFlow::Global<KnownOpenSSLAlgorithmToAlgorithmValueConsumerConfig>;
module RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof KnownOpenSSLAlgorithmConstant
}
predicate isSink(DataFlow::Node sink) {
exists(PaddingAlgorithmValueConsumer c | c.getInputNode() = sink)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
knownPassThroughStep(node1, node2)
}
}
module RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow =
DataFlow::Global<RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig>;
class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep {
OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) }
override DataFlow::Node getOutput() {
exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result)
}
}
abstract class AlgorithmPassthroughCall extends Call {
abstract DataFlow::Node getInNode();
abstract DataFlow::Node getOutNode();
}
class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall {
DataFlow::Node inNode;
DataFlow::Node outNode;
CopyAndDupAlgorithmPassthroughCall() {
// Flow out through any return or other argument of the same type
// Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed
// to be involved
// NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup
this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and
exists(Expr inArg, Type t |
inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType()
|
inNode.asIndirectExpr() = inArg and
(
// Case 1: flow through another argument as an out arg of the same type
exists(Expr outArg |
outArg = this.getAnArgument() and
outArg != inArg and
outArg.getUnspecifiedType().stripType() = t
|
outNode.asDefiningArgument() = outArg
)
or
// Case 2: flow through the return value if the result is the same as the intput type
exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t |
outNode.asIndirectExpr() = outArg
)
)
)
}
override DataFlow::Node getInNode() { result = inNode }
override DataFlow::Node getOutNode() { result = outNode }
}
class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall {
DataFlow::Node inNode;
DataFlow::Node outNode;
NIDToPointerPassthroughCall() {
this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and
inNode.asExpr() = this.getArgument(0) and
outNode.asExpr() = this
//outNode.asIndirectExpr() = this
}
override DataFlow::Node getInNode() { result = inNode }
override DataFlow::Node getOutNode() { result = outNode }
}
class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall {
DataFlow::Node inNode;
DataFlow::Node outNode;
PointerToPointerPassthroughCall() {
this.getTarget().getName() = "OBJ_txt2obj" and
inNode.asIndirectExpr() = this.getArgument(0) and
outNode.asIndirectExpr() = this
or
//outNode.asExpr() = this
this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and
inNode.asIndirectExpr() = this.getArgument(2) and
outNode.asDefiningArgument() = this.getArgument(0)
}
override DataFlow::Node getInNode() { result = inNode }
override DataFlow::Node getOutNode() { result = outNode }
}
class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall {
DataFlow::Node inNode;
DataFlow::Node outNode;
PointerToNIDPassthroughCall() {
this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and
(
inNode.asIndirectExpr() = this.getArgument(0)
or
inNode.asExpr() = this.getArgument(0)
) and
outNode.asExpr() = this
}
override DataFlow::Node getInNode() { result = inNode }
override DataFlow::Node getOutNode() { result = outNode }
}
// TODO: pkeys pass through EVP_PKEY_CTX_new and any similar variant
predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2)
}

View File

@@ -0,0 +1,76 @@
import cpp
import experimental.quantum.Language
import OpenSSLAlgorithmInstanceBase
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
import AlgToAVCFlow
/**
* Given a `KnownOpenSSLBlockModeAlgorithmConstant`, converts this to a block family type.
* Does not bind if there is know mapping (no mapping to 'unknown' or 'other').
*/
predicate knownOpenSSLConstantToBlockModeFamilyType(
KnownOpenSSLBlockModeAlgorithmConstant e, Crypto::TBlockCipherModeOfOperationType type
) {
exists(string name |
name = e.getNormalizedName() and
(
name.matches("CBC") and type instanceof Crypto::CBC
or
name.matches("CFB%") and type instanceof Crypto::CFB
or
name.matches("CTR") and type instanceof Crypto::CTR
or
name.matches("GCM") and type instanceof Crypto::GCM
or
name.matches("OFB") and type instanceof Crypto::OFB
or
name.matches("XTS") and type instanceof Crypto::XTS
or
name.matches("CCM") and type instanceof Crypto::CCM
or
name.matches("GCM") and type instanceof Crypto::GCM
or
name.matches("CCM") and type instanceof Crypto::CCM
or
name.matches("ECB") and type instanceof Crypto::ECB
)
)
}
class KnownOpenSSLBlockModeConstantAlgorithmInstance extends OpenSSLAlgorithmInstance,
Crypto::ModeOfOperationAlgorithmInstance instanceof KnownOpenSSLBlockModeAlgorithmConstant
{
OpenSSLAlgorithmValueConsumer getterCall;
KnownOpenSSLBlockModeConstantAlgorithmInstance() {
// Two possibilities:
// 1) The source is a literal and flows to a getter, then we know we have an instance
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
// Possibility 1:
this instanceof Literal and
exists(DataFlow::Node src, DataFlow::Node sink |
// Sink is an argument to a CipherGetterCall
sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and
// Source is `this`
src.asExpr() = this and
// This traces to a getter
KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
)
or
// Possibility 2:
this instanceof DirectAlgorithmValueConsumer and getterCall = this
}
override Crypto::TBlockCipherModeOfOperationType getModeType() {
knownOpenSSLConstantToBlockModeFamilyType(this, result)
or
not knownOpenSSLConstantToBlockModeFamilyType(this, _) and result = Crypto::OtherMode()
}
// NOTE: I'm not going to attempt to parse out the mode specific part, so returning
// the same as the raw name for now.
override string getRawModeAlgorithmName() { result = this.(Literal).getValue().toString() }
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
}

View File

@@ -0,0 +1,126 @@
import cpp
import experimental.quantum.Language
import KnownAlgorithmConstants
import Crypto::KeyOpAlg as KeyOpAlg
import OpenSSLAlgorithmInstanceBase
import PaddingAlgorithmInstance
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
import AlgToAVCFlow
import BlockAlgorithmInstance
/**
* Given a `KnownOpenSSLCipherAlgorithmConstant`, converts this to a cipher family type.
* Does not bind if there is know mapping (no mapping to 'unknown' or 'other').
*/
predicate knownOpenSSLConstantToCipherFamilyType(
KnownOpenSSLCipherAlgorithmConstant e, Crypto::KeyOpAlg::TAlgorithm type
) {
exists(string name |
name = e.getNormalizedName() and
(
name.matches("AES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::AES())
or
name.matches("ARIA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::ARIA())
or
name.matches("BLOWFISH%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::BLOWFISH())
or
name.matches("BF%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::BLOWFISH())
or
name.matches("CAMELLIA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CAMELLIA())
or
name.matches("CHACHA20%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CHACHA20())
or
name.matches("CAST5%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CAST5())
or
name.matches("2DES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DoubleDES())
or
name.matches("3DES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::TripleDES())
or
name.matches("DES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DES())
or
name.matches("DESX%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DESX())
or
name.matches("GOST%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::GOST())
or
name.matches("IDEA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::IDEA())
or
name.matches("KUZNYECHIK%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::KUZNYECHIK())
or
name.matches("MAGMA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::MAGMA())
or
name.matches("RC2%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC2())
or
name.matches("RC4%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC4())
or
name.matches("RC5%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC5())
or
name.matches("RSA%") and type = KeyOpAlg::TAsymmetricCipher(KeyOpAlg::RSA())
or
name.matches("SEED%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::SEED())
or
name.matches("SM4%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::SM4())
)
)
}
class KnownOpenSSLCipherConstantAlgorithmInstance extends OpenSSLAlgorithmInstance,
Crypto::KeyOperationAlgorithmInstance instanceof KnownOpenSSLCipherAlgorithmConstant
{
OpenSSLAlgorithmValueConsumer getterCall;
KnownOpenSSLCipherConstantAlgorithmInstance() {
// Two possibilities:
// 1) The source is a literal and flows to a getter, then we know we have an instance
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
// Possibility 1:
this instanceof Literal and
exists(DataFlow::Node src, DataFlow::Node sink |
// Sink is an argument to a CipherGetterCall
sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and
// Source is `this`
src.asExpr() = this and
// This traces to a getter
KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
)
or
// Possibility 2:
this instanceof DirectAlgorithmValueConsumer and getterCall = this
}
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() {
// if there is a block mode associated with the same element, then that's the block mode
// note, if none are associated, we may need to parse if the cipher is a block cipher
// to determine if this is an unknown vs not relevant.
result = this
}
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() {
//TODO: the padding is either self, or it flows through getter ctx to a set padding call
// like EVP_PKEY_CTX_set_rsa_padding
result = this
// TODO or trace through getter ctx to set padding
}
override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() }
override string getKeySizeFixed() {
exists(int keySize |
this.(KnownOpenSSLCipherAlgorithmConstant).getExplicitKeySize() = keySize and
result = keySize.toString()
)
}
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
knownOpenSSLConstantToCipherFamilyType(this, result)
or
not knownOpenSSLConstantToCipherFamilyType(this, _) and
result = Crypto::KeyOpAlg::TUnknownKeyOperationAlgorithmType()
}
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
// TODO: trace to any key size initializer, symmetric and asymmetric
none()
}
}

View File

@@ -0,0 +1,83 @@
import cpp
import experimental.quantum.Language
import KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
import AlgToAVCFlow
predicate knownOpenSSLConstantToHashFamilyType(
KnownOpenSSLHashAlgorithmConstant e, Crypto::THashType type
) {
exists(string name |
name = e.getNormalizedName() and
(
name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B
or
name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S
or
name.matches("GOST%") and type instanceof Crypto::GOSTHash
or
name.matches("MD2") and type instanceof Crypto::MD2
or
name.matches("MD4") and type instanceof Crypto::MD4
or
name.matches("MD5") and type instanceof Crypto::MD5
or
name.matches("MDC2") and type instanceof Crypto::MDC2
or
name.matches("POLY1305") and type instanceof Crypto::POLY1305
or
name.matches(["SHA", "SHA1"]) and type instanceof Crypto::SHA1
or
name.matches("SHA+%") and not name.matches(["SHA1", "SHA3-"]) and type instanceof Crypto::SHA2
or
name.matches("SHA3-%") and type instanceof Crypto::SHA3
or
name.matches(["SHAKE"]) and type instanceof Crypto::SHAKE
or
name.matches("SM3") and type instanceof Crypto::SM3
or
name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160
or
name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL
)
)
}
class KnownOpenSSLHashConstantAlgorithmInstance extends OpenSSLAlgorithmInstance,
Crypto::HashAlgorithmInstance instanceof KnownOpenSSLHashAlgorithmConstant
{
OpenSSLAlgorithmValueConsumer getterCall;
KnownOpenSSLHashConstantAlgorithmInstance() {
// Two possibilities:
// 1) The source is a literal and flows to a getter, then we know we have an instance
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
// Possibility 1:
this instanceof Literal and
exists(DataFlow::Node src, DataFlow::Node sink |
// Sink is an argument to a CipherGetterCall
sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and
// Source is `this`
src.asExpr() = this and
// This traces to a getter
KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
)
or
// Possibility 2:
this instanceof DirectAlgorithmValueConsumer and getterCall = this
}
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
override Crypto::THashType getHashFamily() {
knownOpenSSLConstantToHashFamilyType(this, result)
or
not knownOpenSSLConstantToHashFamilyType(this, _) and result = Crypto::OtherHashType()
}
override string getRawHashAlgorithmName() { result = this.(Literal).getValue().toString() }
override int getFixedDigestLength() {
this.(KnownOpenSSLHashAlgorithmConstant).getExplicitDigestLength() = result
}
}

View File

@@ -0,0 +1,6 @@
import experimental.quantum.Language
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
abstract class OpenSSLAlgorithmInstance extends Crypto::AlgorithmInstance {
abstract OpenSSLAlgorithmValueConsumer getAVC();
}

View File

@@ -0,0 +1,5 @@
import OpenSSLAlgorithmInstanceBase
import CipherAlgorithmInstance
import PaddingAlgorithmInstance
import BlockAlgorithmInstance
import HashAlgorithmInstance

View File

@@ -0,0 +1,167 @@
import cpp
import experimental.quantum.Language
import OpenSSLAlgorithmInstanceBase
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import AlgToAVCFlow
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
/**
* Given a `KnownOpenSSLPaddingAlgorithmConstant`, converts this to a padding family type.
* Does not bind if there is know mapping (no mapping to 'unknown' or 'other').
*/
predicate knownOpenSSLConstantToPaddingFamilyType(
KnownOpenSSLPaddingAlgorithmConstant e, Crypto::TPaddingType type
) {
exists(string name |
name = e.getNormalizedName() and
(
name.matches("OAEP") and type = Crypto::OAEP()
or
name.matches("PSS") and type = Crypto::PSS()
or
name.matches("PKCS7") and type = Crypto::PKCS7()
or
name.matches("PKCS1V15") and type = Crypto::PKCS1_v1_5()
)
)
}
//abstract class OpenSSLPaddingAlgorithmInstance extends OpenSSLAlgorithmInstance, Crypto::PaddingAlgorithmInstance{}
// TODO: need to alter this to include known padding constants which don't have the
// same mechanics as those with known nids
class KnownOpenSSLPaddingConstantAlgorithmInstance extends OpenSSLAlgorithmInstance,
Crypto::PaddingAlgorithmInstance instanceof Expr
{
OpenSSLAlgorithmValueConsumer getterCall;
boolean isPaddingSpecificConsumer;
KnownOpenSSLPaddingConstantAlgorithmInstance() {
// three possibilities:
// 1) The source is a 'typical' literal and flows to a getter, then we know we have an instance
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
// 3) the source is a padding-specific literal flowing to a padding-specific consumer
// Possibility 1:
this instanceof Literal and
this instanceof KnownOpenSSLPaddingAlgorithmConstant and
exists(DataFlow::Node src, DataFlow::Node sink |
// Sink is an argument to a CipherGetterCall
sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and
// Source is `this`
src.asExpr() = this and
// This traces to a getter
KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) and
isPaddingSpecificConsumer = false
)
or
// Possibility 2:
this instanceof DirectAlgorithmValueConsumer and
getterCall = this and
this instanceof KnownOpenSSLPaddingAlgorithmConstant and
isPaddingSpecificConsumer = false
or
// Possibility 3:
// from rsa.h in openssl:
// # define RSA_PKCS1_PADDING 1
// # define RSA_NO_PADDING 3
// # define RSA_PKCS1_OAEP_PADDING 4
// # define RSA_X931_PADDING 5
// /* EVP_PKEY_ only */
// # define RSA_PKCS1_PSS_PADDING 6
// # define RSA_PKCS1_WITH_TLS_PADDING 7
// /* internal RSA_ only */
// # define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8
this instanceof Literal and
this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8] and
exists(DataFlow::Node src, DataFlow::Node sink |
// Sink is an argument to a CipherGetterCall
sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and
// Source is `this`
src.asExpr() = this and
// This traces to a padding-specific consumer
RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow::flow(src, sink)
) and
isPaddingSpecificConsumer = true
}
override string getRawPaddingAlgorithmName() { result = this.(Literal).getValue().toString() }
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
override Crypto::TPaddingType getPaddingType() {
isPaddingSpecificConsumer = true and
(
if this.(Literal).getValue().toInt() in [1, 7, 8]
then result = Crypto::PKCS1_v1_5()
else
if this.(Literal).getValue().toInt() = 3
then result = Crypto::NoPadding()
else
if this.(Literal).getValue().toInt() = 4
then result = Crypto::OAEP()
else
if this.(Literal).getValue().toInt() = 5
then result = Crypto::ANSI_X9_23()
else
if this.(Literal).getValue().toInt() = 6
then result = Crypto::PSS()
else result = Crypto::OtherPadding()
)
or
isPaddingSpecificConsumer = false and
knownOpenSSLConstantToPaddingFamilyType(this, result)
}
}
// // Values used for EVP_PKEY_CTX_set_rsa_padding, these are
// // not the same as 'typical' constants found in the set of known algorithm constants
// // they do not have an NID
// // TODO: what about setting the padding directly?
// class KnownRSAPaddingConstant extends OpenSSLPaddingAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Literal
// {
// KnownRSAPaddingConstant() {
// // from rsa.h in openssl:
// // # define RSA_PKCS1_PADDING 1
// // # define RSA_NO_PADDING 3
// // # define RSA_PKCS1_OAEP_PADDING 4
// // # define RSA_X931_PADDING 5
// // /* EVP_PKEY_ only */
// // # define RSA_PKCS1_PSS_PADDING 6
// // # define RSA_PKCS1_WITH_TLS_PADDING 7
// // /* internal RSA_ only */
// // # define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8
// this instanceof Literal and
// this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8]
// // TODO: trace to padding-specific consumers
// RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow
// }
// override string getRawPaddingAlgorithmName() { result = this.(Literal).getValue().toString() }
// override Crypto::TPaddingType getPaddingType() {
// if this.(Literal).getValue().toInt() in [1, 6, 7, 8]
// then result = Crypto::PKCS1_v1_5()
// else
// if this.(Literal).getValue().toInt() = 3
// then result = Crypto::NoPadding()
// else
// if this.(Literal).getValue().toInt() = 4
// then result = Crypto::OAEP()
// else
// if this.(Literal).getValue().toInt() = 5
// then result = Crypto::ANSI_X9_23()
// else result = Crypto::OtherPadding()
// }
// }
class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance,
KnownOpenSSLPaddingConstantAlgorithmInstance
{
OAEPPaddingAlgorithmInstance() {
this.(Crypto::PaddingAlgorithmInstance).getPaddingType() = Crypto::OAEP()
}
override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() {
none() //TODO
}
override Crypto::HashAlgorithmInstance getMGF1HashAlgorithm() {
none() //TODO
}
}

View File

@@ -0,0 +1,39 @@
import cpp
import experimental.quantum.Language
import experimental.quantum.OpenSSL.LibraryDetector
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
import OpenSSLAlgorithmValueConsumerBase
abstract class CipherAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }
// https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html
class EVPCipherAlgorithmValueConsumer extends CipherAlgorithmValueConsumer {
DataFlow::Node valueArgNode;
DataFlow::Node resultNode;
EVPCipherAlgorithmValueConsumer() {
resultNode.asExpr() = this and
isPossibleOpenSSLFunction(this.(Call).getTarget()) and
(
this.(Call).getTarget().getName() in [
"EVP_get_cipherbyname", "EVP_get_cipherbyobj", "EVP_get_cipherbynid"
] and
valueArgNode.asExpr() = this.(Call).getArgument(0)
or
this.(Call).getTarget().getName() in ["EVP_CIPHER_fetch", "EVP_ASYM_CIPHER_fetch"] and
valueArgNode.asExpr() = this.(Call).getArgument(1)
)
}
override DataFlow::Node getResultNode() { result = resultNode }
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
// override DataFlow::Node getInputNode() { result = valueArgNode }
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
//TODO: As a potential alternative, for OpenSSL only, add a generic source node for literals and only create flow (flowsTo) to
// OpenSSL AVCs... the unknown literal sources would have to be any literals not in the known set.
}
}

View File

@@ -0,0 +1,36 @@
import cpp
import experimental.quantum.Language
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
// TODO: can self referential to itself, which is also an algorithm (Known algorithm)
/**
* Cases like EVP_MD5(),
* there is no input, rather it directly gets an algorithm
* and returns it.
*/
class DirectAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer {
DataFlow::Node resultNode;
Expr resultExpr;
DirectAlgorithmValueConsumer() {
this instanceof KnownOpenSSLAlgorithmConstant and
this instanceof Call and
resultExpr = this and
resultNode.asExpr() = resultExpr
}
/**
* These cases take in no explicit value (the value is implicit)
*/
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
override DataFlow::Node getResultNode() { result = resultNode }
// override DataFlow::Node getOutputNode() { result = resultNode }
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
// Note: algorithm source definitions enforces that
// this class will be a known algorithm source
result = this
}
}

View File

@@ -0,0 +1,35 @@
// import EVPHashInitializer
// import EVPHashOperation
// import EVPHashAlgorithmSource
import cpp
import experimental.quantum.Language
import semmle.code.cpp.dataflow.new.DataFlow
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
import experimental.quantum.OpenSSL.LibraryDetector
abstract class HashAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }
/**
* EVP_Q_Digest directly consumes algorithm constant values
*/
class EVP_Q_Digest_Algorithm_Consumer extends OpenSSLAlgorithmValueConsumer {
EVP_Q_Digest_Algorithm_Consumer() {
isPossibleOpenSSLFunction(this.(Call).getTarget()) and
this.(Call).getTarget().getName() = "EVP_Q_digest"
}
override Crypto::ConsumerInputDataFlowNode getInputNode() {
result.asExpr() = this.(Call).getArgument(1)
}
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
}
override DataFlow::Node getResultNode() {
// EVP_Q_Digest directly consumes the algorithm constant value and performs the operation, there is no
// algorithm result
none()
}
}

View File

@@ -0,0 +1,9 @@
import experimental.quantum.Language
import semmle.code.cpp.dataflow.new.DataFlow
abstract class OpenSSLAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof Call {
/**
* Returns the node representing the resulting algorithm
*/
abstract DataFlow::Node getResultNode();
}

View File

@@ -0,0 +1,5 @@
import OpenSSLAlgorithmValueConsumerBase
import CipherAlgorithmValueConsumer
import DirectAlgorithmValueConsumer
import PaddingAlgorithmValueConsumer
import HashAlgorithmValueConsumer

View File

@@ -0,0 +1,36 @@
import cpp
import experimental.quantum.Language
import experimental.quantum.OpenSSL.LibraryDetector
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
import OpenSSLAlgorithmValueConsumerBase
abstract class PaddingAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }
// https://docs.openssl.org/master/man7/EVP_ASYM_CIPHER-RSA/#rsa-asymmetric-cipher-parameters
// TODO: need to handle setting padding through EVP_PKEY_CTX_set_params, where modes like "OSSL_PKEY_RSA_PAD_MODE_OAEP"
// are set.
class EVP_PKEY_CTX_set_rsa_padding_AlgorithmValueConsumer extends PaddingAlgorithmValueConsumer {
DataFlow::Node valueArgNode;
DataFlow::Node resultNode;
EVP_PKEY_CTX_set_rsa_padding_AlgorithmValueConsumer() {
resultNode.asExpr() = this and
isPossibleOpenSSLFunction(this.(Call).getTarget()) and
(
this.(Call).getTarget().getName() in ["EVP_PKEY_CTX_set_rsa_padding"] and
valueArgNode.asExpr() = this.(Call).getArgument(1)
)
}
override DataFlow::Node getResultNode() { result = resultNode }
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
// override DataFlow::Node getInputNode() { result = valueArgNode }
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
//TODO: As a potential alternative, for OpenSSL only, add a generic source node for literals and only create flow (flowsTo) to
// OpenSSL AVCs... the unknown literal sources would have to be any literals not in the known set.
}
}

View File

@@ -0,0 +1,99 @@
//TODO: model as data on open APIs should be able to get common flows, and obviate some of this
// e.g., copy/dup calls, need to ingest those models for openSSL and refactor.
/**
* In OpenSSL, flow between 'context' parameters is often used to
* store state/config of how an operation will eventually be performed.
* Tracing algorithms and configurations to operations therefore
* requires tracing context parameters for many OpenSSL apis.
*
* This library provides a dataflow analysis to track context parameters
* between any two functions accepting openssl context parameters.
* The dataflow takes into consideration flowing through duplication and copy calls
* as well as flow through flow killers (free/reset calls).
*
* TODO: we may need to revisit 'free' as a dataflow killer, depending on how
* we want to model use after frees.
*
* This library also provides classes to represent context Types and relevant
* arguments/expressions.
*/
import semmle.code.cpp.dataflow.new.DataFlow
class CTXType extends Type {
CTXType() {
// TODO: should we limit this to an openssl path?
this.getUnspecifiedType().stripType().getName().matches("evp_%ctx_%st")
}
}
class CTXPointerExpr extends Expr {
CTXPointerExpr() {
this.getType() instanceof CTXType and
this.getType() instanceof PointerType
}
}
class CTXPointerArgument extends CTXPointerExpr {
CTXPointerArgument() { exists(Call c | c.getAnArgument() = this) }
Call getCall() { result.getAnArgument() = this }
}
class CTXClearCall extends Call {
CTXClearCall() {
this.getTarget().getName().toLowerCase().matches(["%free%", "%reset%"]) and
this.getAnArgument() instanceof CTXPointerArgument
}
}
class CTXCopyOutArgCall extends Call {
CTXCopyOutArgCall() {
this.getTarget().getName().toLowerCase().matches(["%copy%"]) and
this.getAnArgument() instanceof CTXPointerArgument
}
}
class CTXCopyReturnCall extends Call {
CTXCopyReturnCall() {
this.getTarget().getName().toLowerCase().matches(["%dup%"]) and
this.getAnArgument() instanceof CTXPointerArgument and
this instanceof CTXPointerExpr
}
}
module OpenSSLCTXArgumentFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CTXPointerArgument }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CTXPointerArgument }
predicate isBarrier(DataFlow::Node node) {
exists(CTXClearCall c | c.getAnArgument() = node.asExpr())
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(CTXCopyOutArgCall c |
c.getAnArgument() = node1.asExpr() and
c.getAnArgument() = node2.asExpr() and
node1.asExpr() != node2.asExpr() and
node2.asExpr().getType() instanceof CTXType
)
or
exists(CTXCopyReturnCall c |
c.getAnArgument() = node1.asExpr() and
c = node2.asExpr() and
node1.asExpr() != node2.asExpr() and
node2.asExpr().getType() instanceof CTXType
)
}
}
module OpenSSLCTXArgumentFlow = DataFlow::Global<OpenSSLCTXArgumentFlowConfig>;
predicate ctxArgFlowsToCtxArg(CTXPointerArgument source, CTXPointerArgument sink) {
exists(DataFlow::Node a, DataFlow::Node b |
OpenSSLCTXArgumentFlow::flow(a, b) and
a.asExpr() = source and
b.asExpr() = sink
)
}

View File

@@ -0,0 +1,7 @@
import cpp
predicate isPossibleOpenSSLFunction(Function f) {
isPossibleOpenSSLLocation(f.getADeclarationLocation())
}
predicate isPossibleOpenSSLLocation(Location l) { l.toString().toLowerCase().matches("%openssl%") }

View File

@@ -0,0 +1,9 @@
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
module OpenSSLModel {
import experimental.quantum.Language
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
}

View File

@@ -0,0 +1,123 @@
/**
* see: https://docs.openssl.org/master/man3/EVP_EncryptInit/
* Models cipher initialization for EVP cipher operations.
*/
import experimental.quantum.Language
import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
module EncValToInitEncArgConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] }
predicate isSink(DataFlow::Node sink) {
exists(EVP_Cipher_Initializer initCall | sink.asExpr() = initCall.getOperationSubtypeArg())
}
}
module EncValToInitEncArgFlow = DataFlow::Global<EncValToInitEncArgConfig>;
int getEncConfigValue(Expr e) {
exists(EVP_Cipher_Initializer initCall | e = initCall.getOperationSubtypeArg()) and
exists(DataFlow::Node a, DataFlow::Node b |
EncValToInitEncArgFlow::flow(a, b) and b.asExpr() = e and result = a.asExpr().getValue().toInt()
)
}
bindingset[i]
Crypto::KeyOperationSubtype intToCipherOperationSubtype(int i) {
if i = 0
then result instanceof Crypto::TEncryptMode
else
if i = 1
then result instanceof Crypto::TDecryptMode
else result instanceof Crypto::TUnknownKeyOperationMode
}
// TODO: need to add key consumer
abstract class EVP_Cipher_Initializer extends Call {
Expr getContextArg() { result = this.(Call).getArgument(0) }
Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
abstract Expr getKeyArg();
abstract Expr getIVArg();
// abstract Crypto::CipherOperationSubtype getCipherOperationSubtype();
abstract Expr getOperationSubtypeArg();
Crypto::KeyOperationSubtype getCipherOperationSubtype() {
if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%")
then result instanceof Crypto::TEncryptMode
else
if this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%")
then result instanceof Crypto::TDecryptMode
else
if exists(getEncConfigValue(this.getOperationSubtypeArg()))
then result = intToCipherOperationSubtype(getEncConfigValue(this.getOperationSubtypeArg()))
else result instanceof Crypto::TUnknownKeyOperationMode
}
}
abstract class EVP_EX_Initializer extends EVP_Cipher_Initializer {
override Expr getKeyArg() { result = this.(Call).getArgument(3) }
override Expr getIVArg() { result = this.(Call).getArgument(4) }
}
abstract class EVP_EX2_Initializer extends EVP_Cipher_Initializer {
override Expr getKeyArg() { result = this.(Call).getArgument(2) }
override Expr getIVArg() { result = this.(Call).getArgument(3) }
}
class EVP_Cipher_EX_Init_Call extends EVP_EX_Initializer {
EVP_Cipher_EX_Init_Call() {
this.(Call).getTarget().getName() in [
"EVP_EncryptInit_ex", "EVP_DecryptInit_ex", "EVP_CipherInit_ex"
]
}
override Expr getOperationSubtypeArg() {
this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and
result = this.(Call).getArgument(5)
}
}
class EVP_Cipher_EX2_or_Simple_Init_Call extends EVP_EX2_Initializer {
EVP_Cipher_EX2_or_Simple_Init_Call() {
this.(Call).getTarget().getName() in [
"EVP_EncryptInit_ex2", "EVP_DecryptInit_ex2", "EVP_CipherInit_ex2", "EVP_EncryptInit",
"EVP_DecryptInit", "EVP_CipherInit"
]
}
override Expr getOperationSubtypeArg() {
this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and
result = this.(Call).getArgument(4)
}
}
class EVP_CipherInit_SKEY_Call extends EVP_EX2_Initializer {
EVP_CipherInit_SKEY_Call() { this.(Call).getTarget().getName() in ["EVP_CipherInit_SKEY"] }
override Expr getOperationSubtypeArg() { result = this.(Call).getArgument(5) }
}
class EVPCipherInitializerAlgorithmArgument extends Expr {
EVPCipherInitializerAlgorithmArgument() {
exists(EVP_Cipher_Initializer initCall | this = initCall.getAlgorithmArg())
}
}
class EVPCipherInitializerKeyArgument extends Expr {
EVPCipherInitializerKeyArgument() {
exists(EVP_Cipher_Initializer initCall | this = initCall.getKeyArg())
}
}
class EVPCipherInitializerIVArgument extends Expr {
EVPCipherInitializerIVArgument() {
exists(EVP_Cipher_Initializer initCall | this = initCall.getIVArg())
}
}

View File

@@ -0,0 +1,116 @@
import experimental.quantum.Language
import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
import EVPCipherInitializer
import OpenSSLOperationBase
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source)
}
predicate isSink(DataFlow::Node sink) {
exists(EVP_Cipher_Operation c | c.getInitCall().getAlgorithmArg() = sink.asExpr())
}
}
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
// import experimental.quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers
// import OpenSSLOperation
// class EVPCipherOutput extends CipherOutputArtifact {
// EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) }
// override DataFlow::Node getOutputNode() { result.asDefiningArgument() = this }
// }
//
/**
* see: https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis
* Base configuration for all EVP cipher operations.
* NOTE: cannot extend instance of OpenSSLOperation, as we need to override
* elements of OpenSSLOperation (i.e., we are creating an instance)
*/
abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperationInstance {
Expr getContextArg() { result = this.(Call).getArgument(0) }
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
result instanceof Crypto::TEncryptMode and
this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%")
or
result instanceof Crypto::TDecryptMode and
this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%")
or
result = this.getInitCall().getCipherOperationSubtype() and
this.(Call).getTarget().getName().toLowerCase().matches("%cipher%")
}
EVP_Cipher_Initializer getInitCall() {
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
}
override Crypto::ConsumerInputDataFlowNode getNonceConsumer() {
this.getInitCall().getIVArg() = result.asExpr()
}
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
this.getInitCall().getKeyArg() = result.asExpr()
}
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
DataFlow::exprNode(this.getInitCall().getAlgorithmArg()))
}
}
// abstract class EVP_Update_Call extends EVP_Cipher_Operation { }
abstract class EVP_Final_Call extends EVP_Cipher_Operation {
override Expr getInputArg() { none() }
}
// TODO: only model Final (model final as operation and model update but not as an operation)
// Updates are multiple input consumers (most important)
// TODO: assuming update doesn't ouput, otherwise it outputs artifacts, but is not an operation
class EVP_Cipher_Call extends EVP_Cipher_Operation {
EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" }
override Expr getInputArg() { result = this.(Call).getArgument(2) }
}
// ******* TODO: model UPDATE but not as the core operation, rather a step towards final
// see the JCA
// class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call {
// EVP_Encrypt_Decrypt_or_Cipher_Update_Call() {
// this.(Call).getTarget().getName() in [
// "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate"
// ]
// }
// override Expr getInputArg() { result = this.(Call).getArgument(3) }
// }
class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call {
EVP_Encrypt_Decrypt_or_Cipher_Final_Call() {
this.(Call).getTarget().getName() in [
"EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal",
"EVP_DecryptFinal", "EVP_CipherFinal"
]
}
}
class EVP_PKEY_Operation extends EVP_Cipher_Operation {
EVP_PKEY_Operation() {
this.(Call).getTarget().getName() in ["EVP_PKEY_decrypt", "EVP_PKEY_encrypt"]
}
override Expr getInputArg() { result = this.(Call).getArgument(3) }
// TODO: how PKEY is initialized is different that symmetric cipher
// Consider making an entirely new class for this and specializing
// the get init call
}
class EVPCipherInputArgument extends Expr {
EVPCipherInputArgument() { exists(EVP_Cipher_Operation op | op.getInputArg() = this) }
}

View File

@@ -0,0 +1,17 @@
import cpp
abstract class EVP_Hash_Initializer extends Call {
Expr getContextArg() { result = this.(Call).getArgument(0) }
abstract Expr getAlgorithmArg();
}
class EVP_DigestInit_Variant_Calls extends EVP_Hash_Initializer {
EVP_DigestInit_Variant_Calls() {
this.(Call).getTarget().getName() in [
"EVP_DigestInit", "EVP_DigestInit_ex", "EVP_DigestInit_ex2"
]
}
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
}

View File

@@ -0,0 +1,117 @@
/**
* https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
*/
import experimental.quantum.Language
import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
import experimental.quantum.OpenSSL.LibraryDetector
import OpenSSLOperationBase
import EVPHashInitializer
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
// import EVPHashConsumers
abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance {
Expr getContextArg() { result = this.(Call).getArgument(0) }
EVP_Hash_Initializer getInitCall() {
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
}
}
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source)
}
predicate isSink(DataFlow::Node sink) {
exists(EVP_Hash_Operation c | c.getInitCall().getAlgorithmArg() = sink.asExpr())
}
}
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
class EVP_Q_Digest_Operation extends EVP_Hash_Operation {
EVP_Q_Digest_Operation() {
this.(Call).getTarget().getName() = "EVP_Q_digest" and
isPossibleOpenSSLFunction(this.(Call).getTarget())
}
//override Crypto::AlgorithmConsumer getAlgorithmConsumer() { }
override EVP_Hash_Initializer getInitCall() {
// This variant of digest does not use an init
// and even if it were used, the init would be ignored/undefined
none()
}
override Expr getOutputArg() { result = this.(Call).getArgument(5) }
override Expr getInputArg() { result = this.(Call).getArgument(3) }
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
// The operation is a direct algorithm consumer
// NOTE: the operation itself is already modeld as a value consumer, so we can
// simply return 'this', see modeled hash algorithm consuers for EVP_Q_Digest
this = result
}
}
class EVP_Digest_Operation extends EVP_Hash_Operation {
EVP_Digest_Operation() {
this.(Call).getTarget().getName() = "EVP_Digest" and
isPossibleOpenSSLFunction(this.(Call).getTarget())
}
// There is no context argument for this function
override Expr getContextArg() { none() }
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
DataFlow::exprNode(this.(Call).getArgument(4)))
}
override EVP_Hash_Initializer getInitCall() {
// This variant of digest does not use an init
// and even if it were used, the init would be ignored/undefined
none()
}
override Expr getOutputArg() { result = this.(Call).getArgument(2) }
override Expr getInputArg() { result = this.(Call).getArgument(0) }
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
}
// // override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
// // AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
// // DataFlow::exprNode(this.getInitCall().getAlgorithmArg()))
// // }
// // ***** TODO *** complete modelinlg for hash operations, but have consideration for terminal and non-terminal (non intermedaite) steps
// // see the JCA. May need to update the cipher operations similarly
// // ALSO SEE cipher for how we currently model initialization of the algorithm through an init call
// class EVP_DigestUpdate_Operation extends EVP_Hash_Operation {
// EVP_DigestUpdate_Operation() {
// this.(Call).getTarget().getName() = "EVP_DigestUpdate" and
// isPossibleOpenSSLFunction(this.(Call).getTarget())
// }
// override Crypto::AlgorithmConsumer getAlgorithmConsumer() {
// this.getInitCall().getAlgorithmArg() = result
// }
// }
// class EVP_DigestFinal_Variants_Operation extends EVP_Hash_Operation {
// EVP_DigestFinal_Variants_Operation() {
// this.(Call).getTarget().getName() in [
// "EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF"
// ] and
// isPossibleOpenSSLFunction(this.(Call).getTarget())
// }
// override Crypto::AlgorithmConsumer getAlgorithmConsumer() {
// this.getInitCall().getAlgorithmArg() = result
// }
// }

View File

@@ -0,0 +1,21 @@
import experimental.quantum.Language
abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call {
abstract Expr getInputArg();
/**
* Can be an argument of a call or a return value of a function.
*/
abstract Expr getOutputArg();
DataFlow::Node getInputNode() {
// Assumed to be default to asExpr
result.asExpr() = this.getInputArg()
}
DataFlow::Node getOutputNode() {
if exists(Call c | c.getAnArgument() = this)
then result.asDefiningArgument() = this
else result.asExpr() = this
}
}

View File

@@ -0,0 +1,3 @@
import OpenSSLOperationBase
import EVPCipherOperation
import EVPHashOperation

View File

@@ -0,0 +1,18 @@
import cpp
private import experimental.quantum.Language
private import LibraryDetector
private import semmle.code.cpp.dataflow.new.DataFlow
class OpenSSLRandomNumberGeneratorInstance extends Crypto::RandomNumberGenerationInstance instanceof Call
{
OpenSSLRandomNumberGeneratorInstance() {
this.(Call).getTarget().getName() in ["RAND_bytes", "RAND_pseudo_bytes"] and
isPossibleOpenSSLFunction(this.(Call).getTarget())
}
override Crypto::DataFlowNode getOutputNode() {
result.asDefiningArgument() = this.(Call).getArgument(0)
}
override string getGeneratorName() { result = this.(Call).getTarget().getName() }
}

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 4.3.1-dev
version: 4.3.2-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
@@ -8,6 +8,7 @@ upgrades: upgrades
dependencies:
codeql/dataflow: ${workspace}
codeql/mad: ${workspace}
codeql/quantum: ${workspace}
codeql/rangeanalysis: ${workspace}
codeql/ssa: ${workspace}
codeql/typeflow: ${workspace}

View File

@@ -1567,7 +1567,7 @@ private int countNumberOfBranchesUsingParameter(SwitchInstruction switch, Parame
|
exists(Ssa::UseImpl use | use.hasIndexInBlock(useblock, _, sv))
or
exists(Ssa::DefImpl def | def.hasIndexInBlock(useblock, _, sv))
exists(Ssa::DefImpl def | def.hasIndexInBlock(sv, useblock, _))
)
)
)
@@ -1814,7 +1814,7 @@ module IteratorFlow {
*/
private predicate isIteratorWrite(Instruction write, Operand address) {
exists(Ssa::DefImpl writeDef, IRBlock bb, int i |
writeDef.hasIndexInBlock(bb, i, _) and
writeDef.hasIndexInBlock(_, bb, i) and
bb.getInstruction(i) = write and
address = writeDef.getAddressOperand()
)

View File

@@ -191,7 +191,7 @@ abstract class DefImpl extends TDefImpl {
* Holds if this definition (or use) has index `index` in block `block`,
* and is a definition (or use) of the variable `sv`
*/
final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
final predicate hasIndexInBlock(SourceVariable sv, IRBlock block, int index) {
this.hasIndexInBlock(block, index) and
sv = this.getSourceVariable()
}
@@ -891,12 +891,12 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
(
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
exists(DefImpl def | def.hasIndexInBlock(v, bb, i) |
if def.isCertain() then certain = true else certain = false
)
or
exists(GlobalDefImpl global |
global.hasIndexInBlock(bb, i, v) and
global.hasIndexInBlock(v, bb, i) and
certain = true
)
)
@@ -934,10 +934,11 @@ module SsaCached {
}
/** Gets the `DefImpl` corresponding to `def`. */
pragma[nomagic]
private DefImpl getDefImpl(SsaImpl::Definition def) {
exists(SourceVariable sv, IRBlock bb, int i |
def.definesAt(sv, bb, i) and
result.hasIndexInBlock(bb, i, sv)
result.hasIndexInBlock(sv, bb, i)
)
}

View File

@@ -58,4 +58,12 @@ class IRFunction extends IRFunctionBase {
* Gets all blocks in this function.
*/
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
/**
* Holds if this function may have incomplete def-use information.
*
* Def-use information may be omitted for a function when it is too expensive
* to compute.
*/
final predicate hasIncompleteSsa() { Construction::hasIncompleteSsa(this) }
}

View File

@@ -235,7 +235,7 @@ private newtype TMemoryLocation =
*
* Some of these memory locations will be filtered out for performance reasons before being passed to SSA construction.
*/
abstract private class MemoryLocation0 extends TMemoryLocation {
abstract class MemoryLocation0 extends TMemoryLocation {
final string toString() {
if this.isMayAccess()
then result = "?" + this.toStringInternal()
@@ -874,7 +874,7 @@ private int numberOfOverlappingUses(MemoryLocation0 def) {
* Holds if `def` is a busy definition. That is, it has a large number of
* overlapping uses.
*/
private predicate isBusyDef(MemoryLocation0 def) { numberOfOverlappingUses(def) > 1024 }
predicate isBusyDef(MemoryLocation0 def) { numberOfOverlappingUses(def) > 1024 }
/** Holds if `use` is a use that overlaps with a busy definition. */
private predicate useOverlapWithBusyDef(MemoryLocation0 use) {

View File

@@ -731,6 +731,20 @@ private module Cached {
or
instruction = getChi(result.(UninitializedGroupInstruction))
}
/**
* Holds if the def-use information for `f` may have been omitted because it
* was too expensive to compute. This happens if one of the memory allocations
* in `f` is a busy definition (i.e., it has many different overlapping uses).
*/
pragma[nomagic]
cached
predicate hasIncompleteSsa(IRFunction f) {
exists(Alias::MemoryLocation0 defLocation |
Alias::isBusyDef(pragma[only_bind_into](defLocation)) and
defLocation.getIRFunction() = f
)
}
}
private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(result) = instr }

View File

@@ -58,4 +58,12 @@ class IRFunction extends IRFunctionBase {
* Gets all blocks in this function.
*/
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
/**
* Holds if this function may have incomplete def-use information.
*
* Def-use information may be omitted for a function when it is too expensive
* to compute.
*/
final predicate hasIncompleteSsa() { Construction::hasIncompleteSsa(this) }
}

View File

@@ -220,6 +220,8 @@ Instruction getMemoryOperandDefinition(
none()
}
predicate hasIncompleteSsa(IRFunction f) { none() }
/**
* Holds if the operand totally overlaps with its definition and consumes the
* bit range `[startBitOffset, endBitOffset)`.

View File

@@ -58,4 +58,12 @@ class IRFunction extends IRFunctionBase {
* Gets all blocks in this function.
*/
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
/**
* Holds if this function may have incomplete def-use information.
*
* Def-use information may be omitted for a function when it is too expensive
* to compute.
*/
final predicate hasIncompleteSsa() { Construction::hasIncompleteSsa(this) }
}

View File

@@ -731,6 +731,20 @@ private module Cached {
or
instruction = getChi(result.(UninitializedGroupInstruction))
}
/**
* Holds if the def-use information for `f` may have been omitted because it
* was too expensive to compute. This happens if one of the memory allocations
* in `f` is a busy definition (i.e., it has many different overlapping uses).
*/
pragma[nomagic]
cached
predicate hasIncompleteSsa(IRFunction f) {
exists(Alias::MemoryLocation0 defLocation |
Alias::isBusyDef(pragma[only_bind_into](defLocation)) and
defLocation.getIRFunction() = f
)
}
}
private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(result) = instr }

View File

@@ -73,6 +73,8 @@ class MemoryLocation extends TMemoryLocation {
final predicate canReuseSsa() { canReuseSsaForVariable(var) }
}
class MemoryLocation0 = MemoryLocation;
predicate canReuseSsaForOldResult(Instruction instr) { none() }
abstract class VariableGroup extends Unit {
@@ -141,3 +143,9 @@ int getStartBitOffset(MemoryLocation location) { none() }
/** Gets the end bit offset of a `MemoryLocation`, if any. */
int getEndBitOffset(MemoryLocation location) { none() }
/**
* Holds if `def` is a busy definition. That is, it has a large number of
* overlapping uses.
*/
predicate isBusyDef(MemoryLocation def) { none() }

View File

@@ -67,8 +67,13 @@ class Class = Cpp::Class; // Used for inheritance conversions
predicate hasCaseEdge(string minValue, string maxValue) { hasCaseEdge(_, minValue, maxValue) }
predicate hasPositionalArgIndex(int argIndex) {
exists(Cpp::FunctionCall call | exists(call.getArgument(argIndex))) or
exists(Cpp::FunctionCall call | exists(call.getArgument(argIndex)))
or
exists(Cpp::BuiltInOperation op | exists(op.getChild(argIndex)))
or
// Ensure we are always able to output the argument of a call to the delete operator.
exists(Cpp::DeleteExpr d) and
argIndex = 0
}
predicate hasAsmOperandIndex(int operandIndex) {

View File

@@ -112,7 +112,14 @@ module SemanticExprConfig {
}
/** Holds if no range analysis should be performed on the phi edges in `f`. */
private predicate excludeFunction(Cpp::Function f) { count(f.getEntryPoint()) > 1 }
private predicate excludeFunction(Cpp::Function f) {
count(f.getEntryPoint()) > 1
or
exists(IR::IRFunction irFunction |
irFunction.getFunction() = f and
irFunction.hasIncompleteSsa()
)
}
SemType getUnknownExprType(Expr expr) { result = getSemanticType(expr.getResultIRType()) }

View File

@@ -1,3 +1,14 @@
## 1.4.0
### Query Metadata Changes
* The tag `external/cwe/cwe-14` has been removed from `cpp/memset-may-be-deleted` and the tag `external/cwe/cwe-014` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api-ir` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/untrusted-data-to-external-api-ir` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/late-check-of-function-argument` and the tag `external/cwe/cwe-020` has been added.
## 1.3.9
No user-facing changes.

View File

@@ -1,6 +1,7 @@
---
category: queryMetadata
---
## 1.4.0
### Query Metadata Changes
* The tag `external/cwe/cwe-14` has been removed from `cpp/memset-may-be-deleted` and the tag `external/cwe/cwe-014` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api-ir` and the tag `external/cwe/cwe-020` has been added.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.3.9
lastReleaseVersion: 1.4.0

View File

@@ -0,0 +1,23 @@
/**
* @name Print CBOM Graph
* @description Outputs a graph representation of the cryptographic bill of materials.
* This query only supports DGML output, as CodeQL DOT output omits properties.
* @kind graph
* @id cpp/print-cbom-graph
* @tags quantum
* experimental
*/
import experimental.quantum.Language
query predicate nodes(Crypto::NodeBase node, string key, string value) {
Crypto::nodes_graph_impl(node, key, value)
}
query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) {
Crypto::edges_graph_impl(source, target, key, value)
}
query predicate graphProperties(string key, string value) {
key = "semmle.graphKind" and value = "graph"
}

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.3.10-dev
version: 1.4.1-dev
groups:
- cpp
- queries

View File

@@ -10,5 +10,5 @@ import internal.CaptureModels
import SummaryModels
from DataFlowSummaryTargetApi api, string flow
where flow = ContentSensitive::captureFlow(api, _)
where flow = ContentSensitive::captureFlow(api, _, _, _, _)
select flow order by flow

View File

@@ -1,15 +0,0 @@
#!/usr/bin/python3
import sys
import os.path
import subprocess
# Add Model as Data script directory to sys.path.
gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
madpath = os.path.join(gitroot, "misc/scripts/models-as-data/")
sys.path.append(madpath)
import generate_flow_model as model
language = "cpp"
model.Generator.make(language).run()

View File

@@ -189,15 +189,15 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Cpp::Lo
)
}
string parameterAccess(Parameter p) { parameterContentAccessImpl(p, result) }
string parameterApproximateAccess(Parameter p) { parameterContentAccessImpl(p, result) }
string parameterContentAccess(Parameter p) { parameterContentAccessImpl(p, result) }
string parameterExactAccess(Parameter p) { parameterContentAccessImpl(p, result) }
bindingset[c]
string paramReturnNodeAsOutput(Callable c, DataFlowPrivate::Position pos) {
string paramReturnNodeAsExactOutput(Callable c, DataFlowPrivate::Position pos) {
exists(Parameter p |
p.isSourceParameterOf(c, pos) and
result = parameterAccess(p)
result = parameterExactAccess(p)
)
or
pos.getArgumentIndex() = -1 and
@@ -206,8 +206,8 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Cpp::Lo
}
bindingset[c]
string paramReturnNodeAsContentOutput(Callable c, DataFlowPrivate::ParameterPosition pos) {
result = paramReturnNodeAsOutput(c, pos)
string paramReturnNodeAsApproximateOutput(Callable c, DataFlowPrivate::ParameterPosition pos) {
result = paramReturnNodeAsExactOutput(c, pos)
}
pragma[nomagic]

View File

@@ -4,7 +4,9 @@ import SummaryModels
import InlineModelsAsDataTest
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(MadRelevantFunction c) { result = ContentSensitive::captureFlow(c, _) }
string getCapturedModel(MadRelevantFunction c) {
result = ContentSensitive::captureFlow(c, _, _, _, _)
}
string getKind() { result = "contentbased-summary" }
}

View File

@@ -4,7 +4,7 @@ import SummaryModels
import InlineModelsAsDataTest
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(MadRelevantFunction c) { result = Heuristic::captureFlow(c) }
string getCapturedModel(MadRelevantFunction c) { result = Heuristic::captureFlow(c, _) }
string getKind() { result = "heuristic-summary" }
}

View File

@@ -10,32 +10,32 @@ namespace Models {
//No model as destructors are excluded from model generation.
~BasicFlow() = default;
//heuristic-summary=Models;BasicFlow;true;returnThis;(int *);;Argument[-1];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnThis;(int *);;Argument[-1];ReturnValue[*];value;df-generated
//contentbased-summary=Models;BasicFlow;true;returnThis;(int *);;Argument[-1];ReturnValue[*];value;dfc-generated
BasicFlow* returnThis(int* input) {
return this;
}
//heuristic-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[*0];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[0];ReturnValue;value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[*0];ReturnValue[*];value;df-generated
//contentbased-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[0];ReturnValue;value;dfc-generated
//contentbased-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[*0];ReturnValue[*];value;dfc-generated
int* returnParam0(int* input0, int* input1) {
return input0;
}
//heuristic-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[1];ReturnValue;taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[*1];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[1];ReturnValue;value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[*1];ReturnValue[*];value;df-generated
//contentbased-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[1];ReturnValue;value;dfc-generated
//contentbased-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[*1];ReturnValue[*];value;dfc-generated
int* returnParam1(int* input0, int* input1) {
return input1;
}
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[1];ReturnValue;taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*1];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[2];ReturnValue;taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*2];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[1];ReturnValue;value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*1];ReturnValue[*];value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[2];ReturnValue;value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*2];ReturnValue[*];value;df-generated
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[1];ReturnValue;value;dfc-generated
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*1];ReturnValue[*];value;dfc-generated
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[2];ReturnValue;value;dfc-generated
@@ -46,9 +46,9 @@ namespace Models {
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];Argument[*1];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[1];ReturnValue;taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];Argument[*1];taint;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];ReturnValue[*];value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[1];ReturnValue;value;df-generated
//heuristic-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];Argument[*1];value;df-generated
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];Argument[*1];taint;dfc-generated
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];ReturnValue[*];taint;dfc-generated
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];ReturnValue[*];value;dfc-generated
@@ -79,14 +79,14 @@ namespace Models {
struct TemplatedFlow {
T tainted;
//heuristic-summary=Models;TemplatedFlow<T>;true;template_returnThis;(T);;Argument[-1];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;template_returnThis;(T);;Argument[-1];ReturnValue[*];value;df-generated
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnThis;(T);;Argument[-1];ReturnValue[*];value;dfc-generated
TemplatedFlow<T>* template_returnThis(T input) {
return this;
}
//heuristic-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[*0];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[0];ReturnValue;value;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[*0];ReturnValue[*];value;df-generated
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[0];ReturnValue;value;dfc-generated
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[*0];ReturnValue[*];value;dfc-generated
T* template_returnParam0(T* input0, T* input1) {
@@ -105,8 +105,8 @@ namespace Models {
return tainted;
}
//heuristic-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[*0];ReturnValue[*];taint;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[0];ReturnValue;value;df-generated
//heuristic-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[*0];ReturnValue[*];value;df-generated
//contentbased-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[0];ReturnValue;value;dfc-generated
//contentbased-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[*0];ReturnValue[*];value;dfc-generated
template<typename U>
@@ -130,7 +130,7 @@ namespace Models {
}
//heuristic-summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;taint;df-generated
//heuristic-summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;value;df-generated
//heuristic-summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;df-generated
//contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;dfc-generated
//contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;dfc-generated
@@ -145,13 +145,13 @@ static int static_toplevel_function(int* p) {
}
struct NonFinalStruct {
//heuristic-summary=;NonFinalStruct;true;public_not_final_member_function;(int);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=;NonFinalStruct;true;public_not_final_member_function;(int);;Argument[0];ReturnValue;value;df-generated
//contentbased-summary=;NonFinalStruct;true;public_not_final_member_function;(int);;Argument[0];ReturnValue;value;dfc-generated
virtual int public_not_final_member_function(int x) {
return x;
}
//heuristic-summary=;NonFinalStruct;false;public_final_member_function;(int);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=;NonFinalStruct;false;public_final_member_function;(int);;Argument[0];ReturnValue;value;df-generated
//contentbased-summary=;NonFinalStruct;false;public_final_member_function;(int);;Argument[0];ReturnValue;value;dfc-generated
virtual int public_final_member_function(int x) final {
return x;
@@ -171,13 +171,13 @@ protected:
};
struct FinalStruct final {
//heuristic-summary=;FinalStruct;false;public_not_final_member_function_2;(int);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=;FinalStruct;false;public_not_final_member_function_2;(int);;Argument[0];ReturnValue;value;df-generated
//contentbased-summary=;FinalStruct;false;public_not_final_member_function_2;(int);;Argument[0];ReturnValue;value;dfc-generated
virtual int public_not_final_member_function_2(int x) {
return x;
}
//heuristic-summary=;FinalStruct;false;public_final_member_function_2;(int);;Argument[0];ReturnValue;taint;df-generated
//heuristic-summary=;FinalStruct;false;public_final_member_function_2;(int);;Argument[0];ReturnValue;value;df-generated
//contentbased-summary=;FinalStruct;false;public_final_member_function_2;(int);;Argument[0];ReturnValue;value;dfc-generated
virtual int public_final_member_function_2(int x) final {
return x;
@@ -211,7 +211,7 @@ struct HasInt {
//contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];value;dfc-generated
//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*0];taint;df-generated
//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*1];taint;df-generated
//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];taint;df-generated
//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];value;df-generated
int copy_struct(HasInt *out, const HasInt *in) {
*out = *in;
return 1;

View File

@@ -0,0 +1,36 @@
#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const __va_list_tag &
#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] __va_list_tag &&
#-----| [Operator,TopLevelFunction] void operator delete(void*)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [VoidPointerType] void *
test.cpp:
# 5| [TopLevelFunction] void foo(int*)
# 5| <params>:
# 5| getParameter(0): [Parameter] x
# 5| Type = [IntPointerType] int *
# 5| getEntryPoint(): [BlockStmt] { ... }
# 6| getStmt(0): [ExprStmt] ExprStmt
# 6| getExpr(): [DeleteExpr] delete
# 6| Type = [VoidType] void
# 6| ValueCategory = prvalue
# 6| getExprWithReuse(): [VariableAccess] x
# 6| Type = [IntPointerType] int *
# 6| ValueCategory = prvalue(load)
# 7| getStmt(1): [ReturnStmt] return ...
# 9| [TopLevelFunction] void bar()
# 9| <params>:
# 11| [TopLevelFunction] void jazz()
# 11| <params>:
# 11| getEntryPoint(): [BlockStmt] { ... }
# 12| getStmt(0): [ExprStmt] ExprStmt
# 12| getExpr(): [FunctionCall] call to bar
# 12| Type = [VoidType] void
# 12| ValueCategory = prvalue
# 13| getStmt(1): [ReturnStmt] return ...

View File

@@ -0,0 +1,11 @@
/**
* @kind graph
*/
private import cpp
private import semmle.code.cpp.PrintAST
private import PrintConfig
private class PrintConfig extends PrintAstConfiguration {
override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) }
}

View File

@@ -0,0 +1,24 @@
private import cpp
/**
* Holds if the specified location is in standard headers.
*/
predicate locationIsInStandardHeaders(Location loc) {
loc.getFile().getAbsolutePath().regexpMatch(".*/include/[^/]+")
}
/**
* Holds if the AST or IR for the specified declaration should be printed in the test output.
*
* This predicate excludes declarations defined in standard headers.
*/
predicate shouldDumpDeclaration(Declaration decl) {
not locationIsInStandardHeaders(decl.getLocation()) and
(
decl instanceof Function
or
decl.(GlobalOrNamespaceVariable).hasInitializer()
or
decl.(StaticLocalVariable).hasInitializer()
)
}

View File

@@ -0,0 +1,38 @@
test.cpp:
# 5| void foo(int*)
# 5| Block 0
# 5| v5_1(void) = EnterFunction :
# 5| m5_2(unknown) = AliasedDefinition :
# 5| m5_3(unknown) = InitializeNonLocal :
# 5| m5_4(unknown) = Chi : total:m5_2, partial:m5_3
# 5| r5_5(glval<int *>) = VariableAddress[x] :
# 5| m5_6(int *) = InitializeParameter[x] : &:r5_5
# 5| r5_7(int *) = Load[x] : &:r5_5, m5_6
# 5| m5_8(unknown) = InitializeIndirection[x] : &:r5_7
# 5| m5_9(unknown) = Chi : total:m5_4, partial:m5_8
# 6| r6_1(glval<unknown>) = FunctionAddress[operator delete] :
# 6| r6_2(glval<int *>) = VariableAddress[x] :
# 6| r6_3(int *) = Load[x] : &:r6_2, m5_6
# 6| v6_4(void) = Call[operator delete] : func:r6_1, 0:r6_3
# 6| m6_5(unknown) = ^CallSideEffect : ~m5_9
# 6| m6_6(unknown) = Chi : total:m5_9, partial:m6_5
# 7| v7_1(void) = NoOp :
# 5| v5_10(void) = ReturnIndirection[x] : &:r5_7, ~m6_6
# 5| v5_11(void) = ReturnVoid :
# 5| v5_12(void) = AliasedUse : ~m6_6
# 5| v5_13(void) = ExitFunction :
# 11| void jazz()
# 11| Block 0
# 11| v11_1(void) = EnterFunction :
# 11| m11_2(unknown) = AliasedDefinition :
# 11| m11_3(unknown) = InitializeNonLocal :
# 11| m11_4(unknown) = Chi : total:m11_2, partial:m11_3
# 12| r12_1(glval<unknown>) = FunctionAddress[bar] :
# 12| v12_2(void) = Call[bar] : func:r12_1
# 12| m12_3(unknown) = ^CallSideEffect : ~m11_4
# 12| m12_4(unknown) = Chi : total:m11_4, partial:m12_3
# 13| v13_1(void) = NoOp :
# 11| v11_5(void) = ReturnVoid :
# 11| v11_6(void) = AliasedUse : ~m12_4
# 11| v11_7(void) = ExitFunction :

View File

@@ -0,0 +1,11 @@
/**
* @kind graph
*/
private import cpp
private import semmle.code.cpp.ir.implementation.aliased_ssa.PrintIR
private import PrintConfig
private class PrintConfig extends PrintIRConfiguration {
override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) }
}

View File

@@ -0,0 +1,13 @@
// Test for edge case, where we have a database without any function calls or
// where none of the function calls have any arguments, but where we do have
// a delete expression.
void foo(int* x) {
delete x;
}
void bar();
void jazz() {
bar();
}

View File

@@ -1,3 +1,7 @@
## 1.7.40
No user-facing changes.
## 1.7.39
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.39
lastReleaseVersion: 1.7.40

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.7.40-dev
version: 1.7.41-dev
groups:
- csharp
- solorigate

View File

@@ -1,3 +1,7 @@
## 1.7.40
No user-facing changes.
## 1.7.39
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.39
lastReleaseVersion: 1.7.40

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.7.40-dev
version: 1.7.41-dev
groups:
- csharp
- solorigate

View File

@@ -1,3 +1,4 @@
ql/csharp/ql/src/API Abuse/CallToGCCollect.ql
ql/csharp/ql/src/API Abuse/FormatInvalid.ql
ql/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql
ql/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql

View File

@@ -1,3 +1,7 @@
## 5.1.6
No user-facing changes.
## 5.1.5
### Minor Analysis Improvements

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 5.1.5
lastReleaseVersion: 5.1.6

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 5.1.6-dev
version: 5.1.7-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

View File

@@ -233,15 +233,28 @@ class InvalidFormatString extends StringLiteral {
}
}
/**
* A method call to a method that parses a format string, for example a call
* to `string.Format()`.
*/
abstract private class FormatStringParseCallImpl extends MethodCall {
/**
* Gets the expression used as the format string.
*/
abstract Expr getFormatExpr();
}
final class FormatStringParseCall = FormatStringParseCallImpl;
/**
* A method call to a method that formats a string, for example a call
* to `string.Format()`.
*/
class FormatCall extends MethodCall {
class FormatCall extends FormatStringParseCallImpl {
FormatCall() { this.getTarget() instanceof FormatMethod }
/** Gets the expression used as the format string. */
Expr getFormatExpr() { result = this.getArgument(this.getFormatArgument()) }
override Expr getFormatExpr() { result = this.getArgument(this.getFormatArgument()) }
/** Gets the argument number containing the format string. */
int getFormatArgument() { result = this.getTarget().(FormatMethod).getFormatArgument() }
@@ -289,3 +302,14 @@ class FormatCall extends MethodCall {
result = this.getArgument(this.getFirstArgument() + index)
}
}
/**
* A method call to `System.Text.CompositeFormat.Parse`.
*/
class ParseFormatStringCall extends FormatStringParseCallImpl {
ParseFormatStringCall() {
this.getTarget() = any(SystemTextCompositeFormatClass x).getParseMethod()
}
override Expr getFormatExpr() { result = this.getArgument(0) }
}

View File

@@ -7,6 +7,7 @@
* @id cs/call-to-gc
* @tags efficiency
* maintainability
* quality
*/
import csharp

View File

@@ -16,22 +16,6 @@ import semmle.code.csharp.frameworks.system.Text
import semmle.code.csharp.frameworks.Format
import FormatFlow::PathGraph
abstract class FormatStringParseCall extends MethodCall {
abstract Expr getFormatExpr();
}
class OrdinaryFormatCall extends FormatStringParseCall instanceof FormatCall {
override Expr getFormatExpr() { result = FormatCall.super.getFormatExpr() }
}
class ParseFormatStringCall extends FormatStringParseCall {
ParseFormatStringCall() {
this.getTarget() = any(SystemTextCompositeFormatClass x).getParseMethod()
}
override Expr getFormatExpr() { result = this.getArgument(0) }
}
module FormatInvalidConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLiteral }

View File

@@ -1,3 +1,20 @@
## 1.2.0
### Query Metadata Changes
* The tag `external/cwe/cwe-13` has been removed from `cs/password-in-configuration` and the tag `external/cwe/cwe-013` has been added.
* The tag `external/cwe/cwe-11` has been removed from `cs/web/debug-binary` and the tag `external/cwe/cwe-011` has been added.
* The tag `external/cwe/cwe-16` has been removed from `cs/web/large-max-request-length` and the tag `external/cwe/cwe-016` has been added.
* The tag `external/cwe/cwe-16` has been removed from `cs/web/request-validation-disabled` and the tag `external/cwe/cwe-016` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cs/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cs/serialization-check-bypass` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cs/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-12` has been removed from `cs/web/missing-global-error-handler` and the tag `external/cwe/cwe-012` has been added.
### Minor Analysis Improvements
* Changed the precision of the `cs/equality-on-floats` query from medium to high.
## 1.1.2
### Minor Analysis Improvements

View File

@@ -20,7 +20,7 @@ module FormatStringConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(FormatCall call | call.hasInsertions()).getFormatExpr()
sink.asExpr() = any(FormatStringParseCall call).getFormatExpr()
}
}

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The precision of the query `cs/uncontrolled-format-string` has been improved (false negative reduction). Calls to `System.Text.CompositeFormat.Parse` are now considered a format like method call.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Changed the precision of the `cs/equality-on-floats` query from medium to high.

View File

@@ -1,6 +1,6 @@
---
category: queryMetadata
---
## 1.2.0
### Query Metadata Changes
* The tag `external/cwe/cwe-13` has been removed from `cs/password-in-configuration` and the tag `external/cwe/cwe-013` has been added.
* The tag `external/cwe/cwe-11` has been removed from `cs/web/debug-binary` and the tag `external/cwe/cwe-011` has been added.
@@ -10,3 +10,7 @@ category: queryMetadata
* The tag `external/cwe/cwe-20` has been removed from `cs/serialization-check-bypass` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-20` has been removed from `cs/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added.
* The tag `external/cwe/cwe-12` has been removed from `cs/web/missing-global-error-handler` and the tag `external/cwe/cwe-012` has been added.
### Minor Analysis Improvements
* Changed the precision of the `cs/equality-on-floats` query from medium to high.

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 1.1.3-dev
version: 1.2.1-dev
groups:
- csharp
- queries

View File

@@ -10,5 +10,5 @@ import internal.CaptureModels
import SummaryModels
from DataFlowSummaryTargetApi api, string flow
where flow = ContentSensitive::captureFlow(api, _)
where flow = ContentSensitive::captureFlow(api, _, _, _, _)
select flow order by flow

View File

@@ -1,15 +0,0 @@
#!/usr/bin/python3
import sys
import os.path
import subprocess
# Add Model as Data script directory to sys.path.
gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
madpath = os.path.join(gitroot, "misc/scripts/models-as-data/")
sys.path.append(madpath)
import generate_flow_model as model
language = "csharp"
model.Generator.make(language).run()

View File

@@ -15,7 +15,7 @@ import PartialFlow::PartialPathGraph
int explorationLimit() { result = 3 }
module PartialFlow = Heuristic::PropagateFlow::FlowExplorationFwd<explorationLimit/0>;
module PartialFlow = Heuristic::PropagateTaintFlow::FlowExplorationFwd<explorationLimit/0>;
from
PartialFlow::PartialPathNode source, PartialFlow::PartialPathNode sink,

View File

@@ -11,16 +11,15 @@
import csharp
import utils.modelgenerator.internal.CaptureModels
import SummaryModels
import Heuristic
import PropagateFlow::PathGraph
import Heuristic::PropagateTaintFlow::PathGraph
from
PropagateFlow::PathNode source, PropagateFlow::PathNode sink, DataFlowSummaryTargetApi api,
DataFlow::Node p, DataFlow::Node returnNodeExt
Heuristic::PropagateTaintFlow::PathNode source, Heuristic::PropagateTaintFlow::PathNode sink,
DataFlowSummaryTargetApi api, DataFlow::Node p, DataFlow::Node returnNodeExt
where
PropagateFlow::flowPath(source, sink) and
Heuristic::PropagateTaintFlow::flowPath(source, sink) and
p = source.getNode() and
returnNodeExt = sink.getNode() and
exists(captureThroughFlow0(api, p, returnNodeExt))
Heuristic::captureThroughFlow0(api, p, returnNodeExt)
select sink.getNode(), source, sink, "There is flow from $@ to the $@.", source.getNode(),
"parameter", sink.getNode(), "return value"

View File

@@ -124,13 +124,13 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Locatio
string qualifierString() { result = "Argument[this]" }
string parameterAccess(CS::Parameter p) {
string parameterApproximateAccess(CS::Parameter p) {
if Collections::isCollectionType(p.getType())
then result = "Argument[" + p.getPosition() + "].Element"
else result = "Argument[" + p.getPosition() + "]"
}
string parameterContentAccess(CS::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
string parameterExactAccess(CS::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
private signature string parameterAccessSig(Parameter p);
@@ -145,13 +145,13 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Locatio
}
bindingset[c]
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterAccess/1>::paramReturnNodeAsOutput(c, pos)
string paramReturnNodeAsApproximateOutput(CS::Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterApproximateAccess/1>::paramReturnNodeAsOutput(c, pos)
}
bindingset[c]
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterContentAccess/1>::paramReturnNodeAsOutput(c, pos)
string paramReturnNodeAsExactOutput(Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterExactAccess/1>::paramReturnNodeAsOutput(c, pos)
}
ParameterPosition getReturnKindParamPosition(ReturnKind kind) {

View File

@@ -39,7 +39,7 @@ private predicate localTypeParameter(Callable callable, TypeParameter tp) {
*/
private predicate parameter(Callable callable, string input, TypeParameter tp) {
exists(Parameter p |
input = ModelGeneratorInput::parameterAccess(p) and
input = ModelGeneratorInput::parameterApproximateAccess(p) and
p = callable.getAParameter() and
(
// Parameter of type tp

View File

@@ -1,3 +1,3 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs
semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs

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