Compare commits

...

370 Commits

Author SHA1 Message Date
Arthur Baars
3990d0e11a Merge pull request #17808 from github/release-prep/2.19.2
Release preparation for version 2.19.2
2024-10-18 17:36:23 +02:00
Arthur Baars
aaf220d41e Fix typos in changelogs 2024-10-18 15:28:05 +00:00
github-actions[bot]
ca0345324e Release preparation for version 2.19.2 2024-10-18 15:16:21 +00:00
Arthur Baars
7c15be1f02 Merge pull request #17806 from github/revert-17764-release-prep/2.19.2
Revert "Release preparation for version 2.19.2"
2024-10-18 17:13:50 +02:00
Arthur Baars
eb515f884b Revert "Release preparation for version 2.19.2" 2024-10-18 17:06:20 +02:00
yoff
8cb339aa93 Merge pull request #17801 from yoff/python/extra-std-models
Python: extra modelling of stdlib
2024-10-18 15:32:01 +02:00
Rasmus Lerchedahl Petersen
30e5a12230 Python: udate expectations 2024-10-18 15:14:51 +02:00
Rasmus Lerchedahl Petersen
30053da70d Python: extra modelling of stdlib
as a reaction to the latest QA run
2024-10-18 13:49:33 +02:00
Paolo Tranquilli
5b2eb88672 Merge pull request #17766 from github/aibaars/fix-cwe-link
Fix CWE coverage link in main index
2024-10-15 14:05:50 +02:00
Arthur Baars
af6fc676ce Fix CWE coverage link in main index 2024-10-15 13:34:38 +02:00
Arthur Baars
15bc417a17 Merge pull request #17764 from github/release-prep/2.19.2
Release preparation for version 2.19.2
2024-10-15 13:08:40 +02:00
Arthur Baars
9ba8045837 Fix typos in changelog entries 2024-10-15 11:06:20 +00:00
github-actions[bot]
255f55cf1a Release preparation for version 2.19.2 2024-10-15 10:29:25 +00:00
Owen Mansel-Chan
1626af0ae1 Merge pull request #17748 from owen-mc/go/join-order-fix/data-flow-node-gettype
Go: Fix bad join order in `SummarizedParameterNode.gettype`
2024-10-15 10:14:38 +01:00
Geoffrey White
7d9a3e1399 Merge pull request #17756 from geoffw0/unusedvar6
Rust: More test cases for rust/unused-variable
2024-10-15 10:02:37 +01:00
Arthur Baars
508e8157b3 Merge pull request #17746 from github/aibaars/macro-pat-irrefutable
Rust: add MacroPat to isExhaustiveMatch
2024-10-15 10:45:06 +02:00
Geoffrey White
5e33d9a145 Rust: Further changes from code review. 2024-10-15 09:38:17 +01:00
Geoffrey White
8169ccd21e Apply suggestions from code review
Co-authored-by: Simon Friis Vindum <paldepind@github.com>
2024-10-15 09:36:09 +01:00
Simon Friis Vindum
cc1e33fb64 Merge pull request #17713 from hvitved/rust/ssa
Rust: Initial SSA implementation
2024-10-15 09:59:48 +02:00
Geoffrey White
57875554f4 Rust: Accept consistency failures in the new test cases. 2024-10-14 17:06:55 +01:00
Geoffrey White
e5885f65db Rust: Add more test cases for unused variables and unreachable code. 2024-10-14 16:25:18 +01:00
Geoffrey White
528641c55a Rust: Test spacing. 2024-10-14 16:25:17 +01:00
Geoffrey White
134539060d Rust: correct some 'spurious' annotations that are off by one line. 2024-10-14 16:24:44 +01:00
Geoffrey White
25b592fc89 Merge pull request #17744 from geoffw0/unusedvar5
Rust: Unused variable follow-up work
2024-10-14 16:20:52 +01:00
Taus
5115216c2d Merge pull request #17755 from github/python/more-adj
python: more adjustments...
2024-10-14 17:16:16 +02:00
yoff
da5e9ac18c python: more adjustments... 2024-10-14 14:54:33 +00:00
Edward Minnix III
ade5686e52 Merge pull request #17335 from egregius313/egregius313/go/dataflow/models/stdin
Go: Implement `stdin` models
2024-10-14 10:38:27 -04:00
Taus
96ea9507a4 Merge pull request #17754 from github/python/extractor-expectations
python: update extractor expectations
2024-10-14 16:35:06 +02:00
yoff
9d8d7ab237 python: update extractor expectations 2024-10-14 14:14:40 +00:00
Arthur Baars
ae7afa7aff Update rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll
Co-authored-by: Simon Friis Vindum <simonfv@gmail.com>
2024-10-14 15:20:43 +02:00
Arthur Baars
867c8a7fa6 Merge branch 'main' into aibaars/macro-pat-irrefutable 2024-10-14 15:02:28 +02:00
Simon Friis Vindum
ef1592fe32 Merge pull request #17751 from paldepind/rust-rename-predicate
Rust: Rename isIrrefutablePattern to isExhaustiveMatch
2024-10-14 14:47:15 +02:00
Arthur Baars
493a68a232 Rust: add MacroPat to isExhaustiveMatch 2024-10-14 13:55:59 +02:00
Simon Friis Vindum
22261c1480 Rust: Rename isIrrefutablePattern to isExhaustiveMatch 2024-10-14 13:43:57 +02:00
Simon Friis Vindum
d0f978d937 Merge pull request #17749 from paldepind/rust-cfg-handle-question-mark
Rust: Handle question mark operator in CFG
2024-10-14 13:19:46 +02:00
Arthur Baars
de612963de Merge pull request #17750 from yoff/python/extractor-test-expectaionts
Python: adjust test expectations for extractor test
2024-10-14 12:54:15 +02:00
Rasmus Lerchedahl Petersen
3402a729d0 Python: adjust test expectations for extractor test 2024-10-14 12:36:56 +02:00
Simon Friis Vindum
e83f1d17bf Rust: Simplify return implementation in CFG 2024-10-14 11:40:35 +02:00
Simon Friis Vindum
8e4e663739 Rust: Handle question mark operator in CFG 2024-10-14 11:38:35 +02:00
Simon Friis Vindum
2f07f1c730 Rust: Abnormal completion in scrutinee does not continue to match arms 2024-10-14 11:32:22 +02:00
Simon Friis Vindum
23ee7b955c Rust: Add CFG tests for question mark operator and scrutinee with return 2024-10-14 11:27:32 +02:00
Owen Mansel-Chan
1456ec2119 Fix bad join order in SummarizedParameterNode.gettype
Specifically the disjunct for this.getPos() != -1. Running on
uber/aresdb, before we had this:

   2403   ~1%    {3} r6 = JOIN `DataFlowUtil::SummarizedParameterNode.getPos/0#dispred#70a2aab4` WITH `DataFlowPrivate::FlowSummaryNode.getSummarizedCallable/0#dispred#e79ea9be` ON FIRST 1 OUTPUT Lhs.1, Lhs.0, Rhs.1
9149774   ~5%    {4}    | JOIN WITH `Types::SignatureType.getParameterType/1#dispred#2c11bb7b_102#join_rhs` ON FIRST 1 OUTPUT Lhs.2, Rhs.1, Lhs.1, Rhs.2
    923   ~9%    {2}    | JOIN WITH `Scopes::Callable.getType/0#dispred#55a0e6a2` ON FIRST 2 OUTPUT Lhs.2, Lhs.3

We add a binding pragma to make it not bind on this.getPos() until
necessary. After we have this:

   2403   ~0%    {3} r6 = JOIN `DataFlowUtil::SummarizedParameterNode.getPos/0#dispred#70a2aab4` WITH `DataFlowPrivate::FlowSummaryNode.getSummarizedCallable/0#dispred#e79ea9be` ON FIRST 1 OUTPUT Rhs.1, Lhs.0, Lhs.1
   2373   ~0%    {3}    | JOIN WITH `Scopes::Callable.getType/0#dispred#55a0e6a2` ON FIRST 1 OUTPUT Rhs.1, Lhs.2, Lhs.1
    923   ~9%    {2}    | JOIN WITH `Types::SignatureType.getParameterType/1#dispred#2c11bb7b` ON FIRST 2 OUTPUT Lhs.2, Rhs.2
2024-10-13 14:27:51 +01:00
Tom Hvitved
6290be2922 Rust: Initial SSA implementation 2024-10-11 19:39:28 +02:00
Tom Hvitved
b0ea175021 Rust: Add more variables tests 2024-10-11 19:36:04 +02:00
yoff
8f681154ce Merge pull request #17683 from yoff/python/flip-default-for-stdlib-extraction
Python: Flip default for stdlib extraction
2024-10-11 18:34:44 +02:00
Geoffrey White
c4256f21c7 Rust: Fix out-of-date spurious tags. 2024-10-11 17:18:41 +01:00
Paolo Tranquilli
5b57826915 Merge pull request #17659 from github/aibaars/rust-macros
Rust: add macro expansion to the extractor
2024-10-11 17:29:29 +02:00
yoff
2af60f1390 Merge pull request #17712 from yoff/python/re-finditer-match
Python: model that `re.finditer` returns an iterable of `re.Match` objects
2024-10-11 16:08:49 +02:00
Arthur Baars
fc298b23c9 Rust: address comment 2024-10-11 16:01:13 +02:00
Arthur Baars
5f45402cf7 Merge remote-tracking branch 'upstream/main' into aibaars/rust-macros 2024-10-11 15:40:07 +02:00
Rasmus Lerchedahl Petersen
5650694313 Python: update tests 2024-10-11 15:36:44 +02:00
Rasmus Lerchedahl Petersen
e2eb08b543 Python: improve messaging 2024-10-11 15:36:44 +02:00
Rasmus Lerchedahl Petersen
22588c9f85 Python: update ectractor version 2024-10-11 15:36:44 +02:00
Rasmus Lerchedahl Petersen
c013d4a59c Python: update test expectations 2024-10-11 15:36:44 +02:00
Rasmus Lerchedahl Petersen
4a291147e0 Python: only look for the py2 stdlib if we extract std lib 2024-10-11 15:36:44 +02:00
Rasmus Lerchedahl Petersen
bb78c2a67e Python: update test expectations 2024-10-11 15:36:44 +02:00
Rasmus Lerchedahl Petersen
e91efaa92e python: do not extract stdlib by default 2024-10-11 15:36:44 +02:00
Tom Hvitved
ac8b9739c5 Merge pull request #17686 from hvitved/rust/cfg-patterns
Rust: Include parameters and patterns in the CFG
2024-10-11 14:45:27 +02:00
Tom Hvitved
ffd6b9864c Address review comments 2024-10-11 14:27:42 +02:00
Arthur Baars
659ce6f1ca Rust: fix CodeQL alert 2024-10-11 13:45:10 +02:00
Arthur Baars
b4bb24aa43 Merge remote-tracking branch 'upstream/main' into aibaars/rust-macros 2024-10-11 13:33:50 +02:00
Arthur Baars
6ade2a8054 Rust: address comments 2024-10-11 13:11:12 +02:00
Paolo Tranquilli
854d7660eb Merge pull request #17730 from github/redsun82/codegen-annotate
Rust: insert `CallExprBase` in the hierarchy
2024-10-11 10:59:40 +02:00
Jeroen Ketema
57c6e4d9cb Merge pull request #17734 from jketema/handle-print
C++: Print handler parameters in PrintAST
2024-10-11 10:53:27 +02:00
Paolo Tranquilli
f3bf347bd6 Merge branch 'main' into redsun82/codegen-annotate 2024-10-11 10:38:02 +02:00
Arthur Baars
9fad5410c0 Rust: implement CFG for macros 2024-10-11 10:37:24 +02:00
Paolo Tranquilli
c66bd72620 Rust: rename to CallExprBase 2024-10-11 09:52:30 +02:00
Ian Lynagh
575eb24073 Merge pull request #17735 from github/revert-17709-go/extractor/objecttypes-consistency-generics
Revert "Go: extractor/objecttypes consistency generics"
2024-10-10 22:20:03 +01:00
Owen Mansel-Chan
d013c8940d Revert "Go: extractor/objecttypes consistency generics" 2024-10-10 21:37:44 +01:00
Tom Hvitved
756affa4aa Rust: Fix bugs in LetExprTree and MethodCallExprTree 2024-10-10 21:05:01 +02:00
Tom Hvitved
2f14ec9f2a Rust: Include patterns in the CFG 2024-10-10 21:05:00 +02:00
Tom Hvitved
f6f54c6e3b Rust: Include parameters in the CFG 2024-10-10 21:04:58 +02:00
Tom Hvitved
665da3958a Rust: Add CFG test for nested function 2024-10-10 21:04:57 +02:00
Jeroen Ketema
f1a350c96a C++: Print handler parameters in PrintAST 2024-10-10 20:47:12 +02:00
Owen Mansel-Chan
d0f73acc25 Merge pull request #17709 from owen-mc/go/extractor/objecttypes-consistency-generics
Go: extractor/objecttypes consistency generics
2024-10-10 17:30:03 +01:00
Tom Hvitved
5f353b72cd Merge pull request #17727 from github/aibaars/modifiers
Rust: add extraction of all sorts of modifier tokens
2024-10-10 18:00:21 +02:00
Simon Friis Vindum
1398575b97 Merge pull request #17728 from paldepind/rust-remove-unused-types
Rust: Remove unused types
2024-10-10 17:33:59 +02:00
Geoffrey White
04c7319b6b Merge pull request #17647 from geoffw0/warnings
Rust: More information about extractor errors and warnings
2024-10-10 16:19:15 +01:00
Geoffrey White
7420d07935 Update ruby/ql/lib/codeql/ruby/AST.qll
Co-authored-by: Arthur Baars <aibaars@github.com>
2024-10-10 15:54:14 +01:00
Mathias Vorreiter Pedersen
e7da53d838 Merge pull request #17715 from MathiasVP/fopen-taint
C++: Add taint through `fopen`
2024-10-10 15:46:46 +01:00
Arthur Baars
6d43eed1e6 Rust: add QL doc for MacroStmts and MacroItems 2024-10-10 16:28:10 +02:00
Paolo Tranquilli
3ef49f31aa Merge pull request #17725 from github/redsun82/fix-cwe-coverage-link
Docs: fix CWE coverage link in main index
2024-10-10 16:18:16 +02:00
Arthur Baars
f97a159163 Rust: clippy fixes 2024-10-10 15:53:16 +02:00
Arthur Baars
88e5ce3cf8 Rust: lower default verbosity to WARN 2024-10-10 15:53:15 +02:00
Arthur Baars
ca27785ace Rust: extract files on a per-project basis
This way we have only one "project" database in-memory at a time. This
should avoid running out of memory when analyzing large mono-repos.
2024-10-10 15:53:14 +02:00
Arthur Baars
db28f1b29e Rust: use macro to inject extraction functions for detached properties 2024-10-10 15:53:13 +02:00
Arthur Baars
8372a2e562 Rust: ensure error and token locations are valid
The locations are "clipped" to the ranges of the parent node of a token,
and the root node of the parse tree for errors.
2024-10-10 15:53:12 +02:00
Arthur Baars
58d2c71c20 Rust: load files from disk ourselves
This avoids problems with files containing invalid utf-8 data, which may cause
panic's like:
```
 thread 'main' panicked at external/rules_rust~~_crate~ql~~r~r__ra_ap_salsa-0.0.232/src/input.rs:91:32:
   no value set for CompressedFileTextQuery(FileId(2429))
   stack backtrace:
      0: rust_begin_unwind
                at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5
      1: core::panicking::panic_fmt
                at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14
      2: <salsa::input::InputStorage<Q> as salsa::plumbing::QueryStorageOps<Q>>::fetch
      3: <DB as ra_ap_base_db::SourceDatabase>::compressed_file_text::__shim
      4: <ra_ap_base_db::FileTextQuery as salsa::plumbing::QueryFunction>::execute
      5: salsa::Cycle::catch
      6: salsa::derived_lru::slot::Slot<Q,MP>::execute
      7: salsa::derived_lru::slot::Slot<Q,MP>::read
      8: <salsa::derived_lru::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch
      9: <DB as ra_ap_base_db::SourceDatabase>::file_text::__shim
     10: <DB as ra_ap_base_db::SourceDatabase>::file_text
     11: <ra_ap_base_db::ParseQuery as salsa::plumbing::QueryFunction>::execute
     12: salsa::Cycle::catch
     13: salsa::derived_lru::slot::Slot<Q,MP>::execute
     14: salsa::derived_lru::slot::Slot<Q,MP>::read
     15: <salsa::derived_lru::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch
     16: <DB as ra_ap_base_db::SourceDatabase>::parse::__shim
     17: <DB as ra_ap_base_db::SourceDatabase>::parse
     18: ra_ap_hir::semantics::SemanticsImpl::parse
     19: single_arch_extractor::main
```
2024-10-10 15:53:11 +02:00
Arthur Baars
f70f8a3536 Rust: fix utf8 test 2024-10-10 15:53:10 +02:00
Arthur Baars
1135bf6bcd Rust: improve QL test script 2024-10-10 15:53:09 +02:00
Arthur Baars
3e877ffaac Rust: do not fail on bad Cargo.toml files 2024-10-10 15:53:08 +02:00
Arthur Baars
ae19b2fd89 Rust: check that TextRanges are for the correct file 2024-10-10 15:53:07 +02:00
Arthur Baars
faa168993c Rust: reduce log output 2024-10-10 15:53:06 +02:00
Arthur Baars
0c10f083cb Rust: set RUST_BACKTRACE=1 2024-10-10 15:53:05 +02:00
Arthur Baars
796da126b8 Rust: update expected output 2024-10-10 15:52:57 +02:00
Arthur Baars
0b3b95ab54 Rust: macro expansion 2024-10-10 15:19:47 +02:00
Arthur Baars
cad2b74137 Rust: integrate Rust Analyzer's Semantic module into extractor 2024-10-10 15:19:46 +02:00
Arthur Baars
6ede20cccc Rust: regenerate code 2024-10-10 15:19:45 +02:00
Arthur Baars
69f0e8bcf7 Rust: add MacroStmts and MacroItems 2024-10-10 15:19:43 +02:00
Arthur Baars
7986fc7036 Rust: avoid double '.' in trap extension 2024-10-10 15:19:42 +02:00
Cornelius Riemenschneider
396bf93ac0 Merge pull request #17716 from github/criemen/rules-kotlin-2.0.0
Upgrade rules_kotlin to 2.0.0.
2024-10-10 15:07:50 +02:00
Geoffrey White
8a895740ba Ruby: Move language specific code out of FileSystem.qll (at least for now). 2024-10-10 14:05:39 +01:00
Owen Mansel-Chan
513efe222d Add check for object for specialized named type 2024-10-10 13:59:51 +01:00
Owen Mansel-Chan
6f6b4a0bfe Add check for specialized objects 2024-10-10 13:59:49 +01:00
Owen Mansel-Chan
d295cac697 Always use generic method object 2024-10-10 13:59:47 +01:00
Paolo Tranquilli
89f43fb917 Rust: generate code 2024-10-10 14:37:40 +02:00
Paolo Tranquilli
6015524589 Rust: insert FunctionOrMethodCallExpr in annotations 2024-10-10 14:34:24 +02:00
Paolo Tranquilli
c364fd7e56 Codegen: allow annotations to replace bases and drop fields 2024-10-10 14:33:06 +02:00
Arthur Baars
32e9881cfb Rust: update expected output 2024-10-10 14:25:07 +02:00
Arthur Baars
30034b4254 Rust: run 'bazel //rust/codegen' 2024-10-10 14:25:06 +02:00
Arthur Baars
b80b6aafdd Rust: extract modifier tokens as predicates 2024-10-10 14:25:05 +02:00
Tom Hvitved
4df9cd88ef Merge pull request #17658 from hvitved/shared/cfg-conditional-splitting
Shared `ConditionalCompletionSplitting` implementation
2024-10-10 13:21:38 +02:00
Simon Friis Vindum
0c9a2896d8 Rust: Remove unused types 2024-10-10 11:47:58 +02:00
Cornelius Riemenschneider
b18f8d3935 Merge pull request #17714 from github/criemen/flip-enable-plus
Bazel: Flip --incompatible_use_plus_in_repo_names.
2024-10-10 11:06:19 +02:00
Cornelius Riemenschneider
6322270926 Merge branch 'main' into criemen/flip-enable-plus 2024-10-10 09:54:16 +02:00
Paolo Tranquilli
3711a7e3e6 Fix CWE coverage link in main index
Kudos to @aikenka for spotting this.

Closes https://github.com/github/codeql/issues/17723
2024-10-10 09:30:20 +02:00
Geoffrey White
25b3d76f71 Merge pull request #17718 from geoffw0/unusedvar4
Rust: Restrict variables to lowercase (for now).
2024-10-10 08:22:52 +01:00
Geoffrey White
09c2f901f4 Merge pull request #17525 from geoffw0/unreachable
Rust: Unreachable code query
2024-10-10 08:22:08 +01:00
Tom Hvitved
6a87eb0c73 Merge pull request #17696 from hvitved/rust/captured-variables
Rust: Account for captured variables
2024-10-09 19:42:03 +02:00
Mathias Vorreiter Pedersen
acac3a06ad C++: Respond to review comments. 2024-10-09 17:32:37 +01:00
Geoffrey White
719cef8298 Merge branch 'main' into unreachable 2024-10-09 17:06:11 +01:00
Geoffrey White
5ac9c2db74 Rust: Accept variables test change. 2024-10-09 17:00:15 +01:00
Edward Minnix III
0abc0d1a67 Fix: ActiveThreatModelSource 2024-10-09 11:35:07 -04:00
Tom Hvitved
aa7215bbd5 Address review comments 2024-10-09 17:22:16 +02:00
Geoffrey White
dfeb35fe1a Rust: Move the restriction to variableDecl. 2024-10-09 16:21:12 +01:00
Jeroen Ketema
8352d17e2c Merge pull request #17693 from jketema/concepts
C++: Add a skeleton class for requires expressions
2024-10-09 16:54:33 +02:00
Geoffrey White
f171eeb229 Rust: Restrict 'unreachable' to nodes intended to be part of the CFG. 2024-10-09 15:37:10 +01:00
Rasmus Lerchedahl Petersen
6bd46148e7 Python: add change note 2024-10-09 16:27:52 +02:00
Geoffrey White
a66f31d844 Rust: Restrict variables to lowercase (for now). 2024-10-09 15:14:27 +01:00
Mathias Vorreiter Pedersen
6965cf7246 C++: Make ql-for-ql happy. 2024-10-09 15:05:13 +01:00
Cornelius Riemenschneider
4de0fefe86 Upgrade rules_kotlin to 2.0.0.
This is required for the bazel 8 upgrade, as one of the
incompatible-flag flips breaks 1.9.4.
2024-10-09 16:04:16 +02:00
Jeroen Ketema
b087fdecfe Merge pull request #17678 from MathiasVP/modernize-unclear-array-index-validation
C++: Modernize `cpp/unclear-array-index-validation`
2024-10-09 15:55:31 +02:00
Tom Hvitved
918e435a48 Merge pull request #17690 from hvitved/rust/ast-consistency-queries
Rust: Add AST consistency queries
2024-10-09 15:54:51 +02:00
Tom Hvitved
04d1c82005 Merge pull request #17689 from hvitved/rust/print-ast
Rust: `PrintAst` improvements
2024-10-09 15:54:30 +02:00
Mathias Vorreiter Pedersen
954235ecdd C++: Add change note. 2024-10-09 14:42:36 +01:00
Mathias Vorreiter Pedersen
338e82064e C++: Add a taint model for 'fopen' and accept test changes. 2024-10-09 14:40:26 +01:00
Mathias Vorreiter Pedersen
201842d2f9 C++: Add test with missing flow through 'fopen'. 2024-10-09 14:39:24 +01:00
Mathias Vorreiter Pedersen
61a012fc6c C++: Don't allow 'x < 0' as a barrier guard. 2024-10-09 14:17:56 +01:00
Mathias Vorreiter Pedersen
c883aa09f8 Update cpp/ql/src/change-notes/2024-10-07-unclear-array-index-validation.md
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2024-10-09 13:45:18 +01:00
Michael Nebel
79871aa51e Merge pull request #17687 from michaelnebel/modelgen/removeduplicatedf
C#/Java: Avoid `df` and `dfc` overlap in model generation.
2024-10-09 14:04:31 +02:00
Cornelius Riemenschneider
4c21444dd5 Bazel: Flip --incompatible_use_plus_in_repo_names.
We've hardcoded the tilde in a lot of places :(
This improves performance on Windows and gets us ready for Bazel 8.

We need an upgrade of rules_rust for this to work.
2024-10-09 14:04:05 +02:00
Geoffrey White
ed39c465a6 Merge pull request #17710 from geoffw0/unusedvar3
Rust: More test cases for unused variables
2024-10-09 12:44:58 +01:00
Michael Nebel
5d4ceeebb5 Shared: Only generate df summary model in the mixed query in case no context sensitive model exist. 2024-10-09 13:04:32 +02:00
Geoffrey White
f3d727fadc Rust: Correct spurious annotations. 2024-10-09 11:52:24 +01:00
Geoffrey White
fa1c92dbe7 Rust: Another case worth having. 2024-10-09 11:50:29 +01:00
Rasmus Lerchedahl Petersen
0ac4a10345 Python: model that finditer returns iterable of re.Match objects 2024-10-09 12:42:38 +02:00
Rasmus Lerchedahl Petersen
494b8bd7e1 python: model string property of resultof finditer 2024-10-09 12:40:47 +02:00
Rasmus Lerchedahl Petersen
073189ed6b python: add test for re.Match objects returned from finditer 2024-10-09 12:32:51 +02:00
Geoffrey White
7a6eabc8a3 Rust: Additional test cases. 2024-10-09 11:31:44 +01:00
yoff
6ffdf576d0 Merge pull request #17708 from yoff/python/ignore-extractor-test-output
Python: ignore some extractor test output
2024-10-09 12:31:42 +02:00
yoff
0b0e8a4bf5 Update python/extractor/tests/parser/.gitignore
As suggested by @tausbn
2024-10-09 12:22:17 +02:00
Chris Smowton
58fd1a2241 Merge pull request #17357 from smowton/smowton/feature/go-indistinguishable-types
Go: extract and expose struct tags, interface method IDs
2024-10-09 11:06:02 +01:00
Rasmus Lerchedahl Petersen
ad630bc6ff Python: ignore some extractor test output
If you test the extractor locally, you want to ignore these files.
2024-10-09 11:34:58 +02:00
Jeroen Ketema
4d251b96a6 C++: Fix copy&paste error in QLDoc 2024-10-09 11:24:08 +02:00
Tom Hvitved
bdb793ba92 Swift: Adopt shared ConditionalCompletionSplitting implementation 2024-10-09 11:02:18 +02:00
Tom Hvitved
3a098d7449 Ruby: Adopt shared ConditionalCompletionSplitting implementation 2024-10-09 11:02:17 +02:00
Tom Hvitved
5d925d36d3 C#: Adopt shared ConditionalCompletionSplitting implementation 2024-10-09 11:02:15 +02:00
Tom Hvitved
3d95369608 Shared ConditionalSplitting implementation 2024-10-09 11:02:13 +02:00
Tom Hvitved
11016e193c Rust: PrintAst improvements 2024-10-09 10:41:30 +02:00
Geoffrey White
41218fb89f Rust: Test spacing / variable names. 2024-10-09 09:17:24 +01:00
Tom Hvitved
5afd2d5bf0 Rust: Account for captured variables 2024-10-09 10:17:01 +02:00
Tom Hvitved
a3a0c2b269 Rust: Add more variable tests 2024-10-09 10:17:00 +02:00
Tom Hvitved
9952997b48 Shared: Add DenseRank library 2024-10-09 10:16:59 +02:00
Jeroen Ketema
f3cbf86c43 Merge pull request #17703 from jketema/odr-test
C++: Fix ODR violations in tests
2024-10-09 10:16:24 +02:00
Jeroen Ketema
723236d15b C++: Add a skeleton class for requires expressions 2024-10-09 02:16:20 +02:00
Jeroen Ketema
c90d0faaf6 C++: Fix ODR violations in dataflow tests 2024-10-08 20:34:20 +02:00
Chris Smowton
837387aeae Re-optimise isSensitive routine 2024-10-08 19:23:31 +01:00
Chris Smowton
629a7a601d Further optimise guardingFunction: remove redundant condition, and order guard -> guardFunction case to work backwards from interesting return sites, allowing us to go backwards not forwards through BasicBlock::dominates 2024-10-08 19:23:30 +01:00
Chris Smowton
d401891d30 copyedit 2024-10-08 19:23:29 +01:00
Chris Smowton
c79da8b2b5 Avoid pathological case where getExampleMethodName picks a very common method name 2024-10-08 19:23:28 +01:00
Chris Smowton
ed9a6bd820 Further join order optimisations 2024-10-08 19:23:27 +01:00
Chris Smowton
bf5ba33c2e Improve join orders for top 5 perf regressions in QA 2024-10-08 19:23:26 +01:00
Chris Smowton
365ccf4903 autoformat 2024-10-08 19:23:25 +01:00
Chris Smowton
36a031833f Further optimisation 2024-10-08 19:23:24 +01:00
Chris Smowton
ab99509a11 Rework interface for querying private interface method ids 2024-10-08 19:23:22 +01:00
Chris Smowton
0f95a8d724 Clarify doc 2024-10-08 19:23:21 +01:00
Chris Smowton
288e0ec565 component_tags -> struct_tags 2024-10-08 19:23:20 +01:00
Chris Smowton
c1a1edf24e Autoformat 2024-10-08 19:23:19 +01:00
Chris Smowton
74cba9056b Optimise join orders 2024-10-08 19:23:18 +01:00
Chris Smowton
d04a0f4b87 Add note explaining how to regenerate dbscheme 2024-10-08 19:23:17 +01:00
Chris Smowton
1511927a2b Remove unnecessary table population on upgrade 2024-10-08 19:23:15 +01:00
Chris Smowton
fd615fb7a3 Prevent bad magic 2024-10-08 19:23:14 +01:00
Chris Smowton
442e58188b Update stats 2024-10-08 19:23:13 +01:00
Chris Smowton
e1963a5fcd autoformat 2024-10-08 19:23:12 +01:00
Chris Smowton
7a7ff4a91e Apply review comments 2024-10-08 19:23:11 +01:00
Chris Smowton
5d14070cd4 Fix test file 2024-10-08 19:23:10 +01:00
Chris Smowton
22ed2f9ae3 Autoformat CodeQL 2024-10-08 19:23:09 +01:00
Chris Smowton
9bb2a4bfce Change note 2024-10-08 19:23:07 +01:00
Chris Smowton
dcbb66d366 Go: extract and expose struct tags, interface method IDs
This enables us to distinguish all database types in QL. Previously structs with the same field names and types but differing tags, and interface types with matching method names and at least one non-exported method but declared in differing packages, were impossible or only sometimes possible to distinguish in QL. With this change these types can be distinguished, as well as permitting queries to examine struct field tags, e.g. to read JSON field name associations.
2024-10-08 19:23:06 +01:00
Jeroen Ketema
f1e22687ab C++: Fix ODR violations in tests
In QLtest we do not have linkage awareness, so having multiple functions with
the same name in the same test causes ODR violations.
2024-10-08 20:09:31 +02:00
yoff
1f1b1b7aab Merge pull request #17653 from yoff/python/typetracking-through-comprehensions 2024-10-08 19:39:21 +02:00
Taus
3c1a19c5ab Merge pull request #17700 from github/tausbn/update-cors-query-change-note-and-tags
Python: Update CORS query tags and change note
2024-10-08 18:05:30 +02:00
Taus
92bca9c268 Python: Update CORS query tags and change note
Makes it more clear that the query is experimental.
2024-10-08 15:44:29 +00:00
Florin Coada
98f52589b0 Merge pull request #17684 from github/changedocs/2.19.1
Adding unified changelog for 2.19.1
2024-10-08 16:41:18 +01:00
Tom Hvitved
fcf1b6d6f5 Merge pull request #17657 from hvitved/rust/cfg-conditional-splitting
Rust: Implement `ConditionalCompletionSplitting`
2024-10-08 16:21:14 +02:00
Tom Hvitved
08d6d54961 Rust: Add AST consistency queries 2024-10-08 15:00:38 +02:00
Geoffrey White
70d530a49c Rust: Exclude nodes that aren't part of the CFG. 2024-10-08 13:52:15 +01:00
Geoffrey White
a7dbe29448 Rust: Add parenthesis example to test. 2024-10-08 13:50:17 +01:00
Geoffrey White
7235ba8f91 Rust: Fix test compilation errors. 2024-10-08 13:38:33 +01:00
Geoffrey White
3b1d917c2b Rust: Autoformat. 2024-10-08 13:30:28 +01:00
Tom Hvitved
cb1ca4c75c Update rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2024-10-08 13:41:24 +02:00
Arthur Baars
4ab925507d Merge pull request #17682 from github/redsun82/rust-codegen
Rust: integrate rust code generation into `//rust/codegen`
2024-10-08 13:23:20 +02:00
Geoffrey White
6bde26d9fd Rust: Switch firstUnreachable to hvitved's suggested implementation. 2024-10-08 12:07:44 +01:00
Geoffrey White
5d7a92cf13 Rust: Add example from discussion. 2024-10-08 12:00:53 +01:00
Geoffrey White
40096ebb62 Rust: More cleanup after merge. 2024-10-08 11:46:45 +01:00
Geoffrey White
9e3f4cd183 Rust: Accept test changes after merging main. 2024-10-08 11:43:31 +01:00
Geoffrey White
483370d5f4 Merge branch 'main' into unreachable 2024-10-08 11:40:03 +01:00
Geoffrey White
f084bb7bcf Rust: A couple of interesting cases with short-circuiting. 2024-10-08 11:38:23 +01:00
Florin Coada
36937a0988 Adding unified changelog for 2.19.1 2024-10-08 11:28:15 +01:00
Jonas Jensen
51d189d30d Merge pull request #17556 from d10c/d10c/bigint-docs
BigInt Documentation
2024-10-08 11:46:58 +02:00
Jeroen Ketema
3d6965a550 Merge pull request #17665 from jketema/printir-doc
C++: Add some documentation on the printed IR
2024-10-08 11:09:56 +02:00
Mathias Vorreiter Pedersen
b00c545799 C++: Add change notes. 2024-10-08 10:08:16 +01:00
Mathias Vorreiter Pedersen
d6618edf01 C++: Accept test changes. 2024-10-08 10:08:14 +01:00
Mathias Vorreiter Pedersen
f7392d6498 C++: Range analysis of 'getc'. 2024-10-08 10:08:13 +01:00
Mathias Vorreiter Pedersen
6ca978e1cc C++: Add FP test. 2024-10-08 10:08:12 +01:00
Mathias Vorreiter Pedersen
823d5acd69 C++: Spacing. 2024-10-08 10:05:11 +01:00
Mathias Vorreiter Pedersen
8bb21e1b49 C++: Accept test changes. 2024-10-08 10:05:10 +01:00
Mathias Vorreiter Pedersen
a2cdb9c173 C++: Use range analysis at the sink to exclude trivial FPs. 2024-10-08 10:05:08 +01:00
Mathias Vorreiter Pedersen
c3d9ea1820 C++: Add FP. 2024-10-08 10:05:07 +01:00
Mathias Vorreiter Pedersen
afb5e4f841 C++: Add test spacing. 2024-10-08 10:05:06 +01:00
Mathias Vorreiter Pedersen
f6f5f5d4b4 C++: Accept test changes. 2024-10-08 10:05:04 +01:00
Mathias Vorreiter Pedersen
c9bd9e9303 C++: Modernize the 'cpp/unclear-array-index-validation' query by getting rid of the DefaultTaintTracking barriers and replacing them with a 'BarrierGuard' instantiation. 2024-10-08 10:05:03 +01:00
Paolo Tranquilli
61c3aa6288 Rust: integrate rust code generation into //rust/codegen 2024-10-08 10:37:53 +02:00
Nora Dimitrijević
328f322692 BigInt documentation 2024-10-08 10:15:06 +02:00
Nora Dimitrijević
26ac84aa6e Fix trailing whitespace in docs 2024-10-08 10:15:03 +02:00
Paolo Tranquilli
96dda8808c Rust: rename generate-schema -> ast-generator 2024-10-08 10:03:00 +02:00
Asger F
5a4cd1c578 Merge pull request #17661 from asgerf/shared/js-useuse-ssa-changes
SSA: Add BarrierGuardWithState
2024-10-08 08:27:18 +02:00
Jeroen Ketema
ed266dac5f C++: Address review comments 2024-10-07 22:42:18 +02:00
Asger F
1ce0ba5083 SSA: Make WithState private 2024-10-07 14:48:28 +02:00
Michael B. Gale
9bfd461fad Merge pull request #17669 from github/dependabot/go_modules/go/extractor/extractor-dependencies-ae022431d0
Bump golang.org/x/tools from 0.25.0 to 0.26.0 in /go/extractor in the extractor-dependencies group
2024-10-07 11:44:05 +01:00
dependabot[bot]
26f8e64a35 Bump golang.org/x/tools
Bumps the extractor-dependencies group in /go/extractor with 1 update: [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/tools` from 0.25.0 to 0.26.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 09:26:56 +00:00
Chris Smowton
770774ed52 Merge pull request #17671 from hvitved/go/fix-tests
Go: Update expected test output
2024-10-07 09:23:59 +01:00
Tom Hvitved
c15749f342 Merge pull request #17672 from hvitved/swift/fix-test
Swift: Update expected test output
2024-10-07 10:07:20 +02:00
Tom Hvitved
6196fd2cc1 Swift: Update expected test output 2024-10-07 09:45:08 +02:00
Arthur Baars
c04315a7cf Merge pull request #17670 from hvitved/ruby/fix-test
Ruby: Fix expected test output
2024-10-07 09:44:51 +02:00
Tom Hvitved
16feaf15e2 Go: Update expected test output 2024-10-07 09:23:39 +02:00
Tom Hvitved
f1afa2bf59 Ruby: Fix expected test output 2024-10-07 09:16:12 +02:00
Owen Mansel-Chan
927b402a3a Merge pull request #17668 from igfoo/igfoo/typo
Java: Typo in a comment
2024-10-06 13:22:08 +01:00
Ian Lynagh
d24bdbb4e4 Java: Typo in a comment 2024-10-04 17:34:39 +01:00
yoff
6bb98b02a8 Merge pull request #17577 from yoff/python/add-comprehension-capture-flow
python: capture flow through comprehensions
2024-10-04 15:51:06 +02:00
Jeroen Ketema
b8eb2ab100 C++: Add some documentation on the printed IR 2024-10-04 15:37:22 +02:00
Rasmus Lerchedahl Petersen
6f5b949ec8 Python: adjust test expectations
note that we do retain precision in
`test_dict_from_keyword()`
2024-10-04 15:30:02 +02:00
Tom Hvitved
04a4fb2143 Merge pull request #17655 from hvitved/rust/variable-mut
Rust: `&(mut) x` is neither a read nor a write
2024-10-04 15:29:36 +02:00
Rasmus Lerchedahl Petersen
a4c1a622b7 Merge branch 'main' of https://github.com/github/codeql into python/add-comprehension-capture-flow 2024-10-04 14:53:03 +02:00
Tom Hvitved
50c2d108ca Rust: Fix CompoundAssignmentExpr charpred 2024-10-04 14:48:07 +02:00
yoff
306b087b6e Merge pull request #17566 from yoff/python/dict-can-take-multiple-args
Python: All dict constructor args are relevant
2024-10-04 14:30:10 +02:00
Rasmus Lerchedahl Petersen
977767b0d6 Python: comment around dictionary comprehensions 2024-10-04 14:14:30 +02:00
Rasmus Lerchedahl Petersen
201c4aad13 Python: add comment 2024-10-04 14:09:33 +02:00
yoff
c064a9e092 Update python/ql/lib/semmle/python/frameworks/Stdlib.qll
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-10-04 14:01:18 +02:00
Tom Hvitved
db5e452178 Merge pull request #17536 from hvitved/ql-test-source-root
Adapt to `sourceLocationPrefix` change in `qltest`
2024-10-04 12:48:51 +02:00
Michael Nebel
c629867191 Merge pull request #17654 from michaelnebel/modelgen/mixedbugfix
C#/Java: Only use heuristic if no content based model exist (in mixed mode).
2024-10-04 10:28:49 +02:00
Tom Hvitved
d0ca39fb03 JS: Update expected test output 2024-10-04 08:35:33 +02:00
Tom Hvitved
b3b9406e45 Python: Update test 2024-10-04 08:35:32 +02:00
Tom Hvitved
953461d1aa C++: Update expected test output 2024-10-04 08:35:31 +02:00
Tom Hvitved
bf0675e5ba Kotlin: Update two tests 2024-10-04 08:35:30 +02:00
Tom Hvitved
2832318711 Java: Account for top-level res folders in AndroidLayoutXmlFile 2024-10-04 08:35:28 +02:00
Tom Hvitved
aa5e0c39ba Rust: Implement ConditionalCompletionSplitting 2024-10-03 21:25:50 +02:00
Tom Hvitved
a9cf33ce18 Rust: &x is neither a read nor a write 2024-10-03 20:20:59 +02:00
Angela P Wen
8542992b0d Merge pull request #17651 from github/post-release-prep/codeql-cli-2.19.1
Post-release preparation for codeql-cli-2.19.1
2024-10-03 11:18:54 -07:00
Tom Hvitved
05f85497ed Rust: Add &mut variable tests 2024-10-03 19:55:07 +02:00
Geoffrey White
d4414dabff Ruby: Add change notes. 2024-10-03 17:40:18 +01:00
Geoffrey White
86cc2dc5a1 Ruby: Add rb/diagnostics/extraction-warnings so that we don't miss anything we had before. 2024-10-03 17:40:17 +01:00
Geoffrey White
1ea94faccf Ruby: Make similar changes to differentiate extraction errors and warnings, and mostly restore original behaviour. 2024-10-03 17:39:56 +01:00
Geoffrey White
4c7ec59306 Ruby: Sync identical files. 2024-10-03 17:17:37 +01:00
Chris Smowton
321eb34eff Merge pull request #17637 from smowton/smowton/admin/go-test-extraction-tests
Go: augment test-extraction tests
2024-10-03 16:06:53 +01:00
Geoffrey White
2e772a80c4 Rust: Accept minor consistency .expected changes. 2024-10-03 15:15:32 +01:00
Geoffrey White
64720adccb Merge pull request #17656 from geoffw0/unusedvar2
Rust: Diagnose unused variable false positives
2024-10-03 14:56:27 +01:00
Michael Nebel
7600c243de Merge pull request #17639 from felickz/patch-1
Update Comment - Clarify threat model flow sources comment in LogForgingQuery.qll
2024-10-03 15:51:40 +02:00
Geoffrey White
369241e1ea Merge pull request #5 from hvitved/unusedvar2
Rust: Account for variables bound in `while let` expressions
2024-10-03 14:04:38 +01:00
Geoffrey White
ccaf2dd9ea Rust: Temporarily limit results (hopefully enough for the DCA job to cope). 2024-10-03 13:44:04 +01:00
yoff
88b3d1ffd7 Merge pull request #17565 from yoff/python/model-urllib-parse-parse-qs
Python: model `urllib.parse.parse_qs`
2024-10-03 14:32:08 +02:00
Tom Hvitved
cd04500dd9 Rust: Account for variables bound in while let expressions 2024-10-03 14:05:24 +02:00
Geoffrey White
3c777b7605 Merge branch 'main' into warnings 2024-10-03 12:54:56 +01:00
Geoffrey White
32dbdb3913 Rust: Update summary stats .expected file. 2024-10-03 12:50:59 +01:00
Geoffrey White
da84889242 Rust: Use @diagnostic_error, @diagnostic_warning rather than constants. 2024-10-03 12:50:40 +01:00
Asger F
9902874ddd SSA: Add BarrierGuardWithState 2024-10-03 13:48:44 +02:00
Geoffrey White
0304aa846c Rust: Add more tests for uused variables. 2024-10-03 12:37:02 +01:00
Rasmus Lerchedahl Petersen
777279dc29 Python: MaD test expectations 2024-10-03 13:29:56 +02:00
Geoffrey White
821398715c Rust: Test spacing. 2024-10-03 11:55:11 +01:00
Rasmus Lerchedahl Petersen
768d866e72 python: model urllib.parse.parse_qs 2024-10-03 12:20:40 +02:00
Rasmus Lerchedahl Petersen
0462809edc Python: add taint test for urllib 2024-10-03 12:20:38 +02:00
Rasmus Lerchedahl Petersen
5c68bad2f1 Python: add comments 2024-10-03 12:17:59 +02:00
yoff
91f1cf10a7 Merge pull request #17454 from yoff/stdlib-optparse
Python: Several standard library models
2024-10-03 12:02:22 +02:00
Tom Hvitved
97c2387904 Merge pull request #17644 from hvitved/rust/break-continue-target 2024-10-03 11:38:27 +02:00
yoff
56d0affe38 Update python/ql/lib/semmle/python/frameworks/Stdlib.model.yml
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-10-03 10:18:25 +02:00
Rasmus Lerchedahl Petersen
6d486f9931 Python: move change note to the right place 2024-10-03 10:15:55 +02:00
Rasmus Lerchedahl Petersen
9e808c17af Python: add change note 2024-10-03 10:09:59 +02:00
Rasmus Lerchedahl Petersen
0dc036abd1 Python: Allow type tracking through comprehensions
- the subscript operator is extended to comprehensions
- the capture jump-step is extended to work for the functions generated inside comprehensions
2024-10-03 09:31:02 +02:00
github-actions[bot]
98d587c482 Post-release preparation for codeql-cli-2.19.1 2024-10-02 22:40:35 +00:00
Angela P Wen
569b650916 Merge pull request #17649 from github/release-prep/2.19.1
Release preparation for version 2.19.1
2024-10-02 11:36:20 -07:00
github-actions[bot]
fe54961b84 Release preparation for version 2.19.1 2024-10-02 18:30:42 +00:00
Angela P Wen
b16ba61fcb Merge pull request #17636 from github/revert-17629-release-prep/2.19.1
Revert "Release preparation for version 2.19.1"
2024-10-02 11:27:40 -07:00
Geoffrey White
88abc8f72f Rust: Add to summary stats. 2024-10-02 18:43:26 +01:00
Geoffrey White
a4c06b2bbc Rust: Define SuccessfullyExtractedFile and use it to simplify queries. 2024-10-02 18:43:25 +01:00
Geoffrey White
12fbd18f3a Rust: Have ExtractionConsistency.ql report both. 2024-10-02 18:43:24 +01:00
Geoffrey White
ad7c96554f Rust: Correct extraction errors query to output only errors. 2024-10-02 18:43:15 +01:00
Geoffrey White
f30a642c8f Rust: Add a test for the extractor warnings query. 2024-10-02 18:42:37 +01:00
Geoffrey White
ba9c2f1e3a Rust: Add extractor warnings query. 2024-10-02 18:42:32 +01:00
Chris Smowton
05d2e16de3 autoformat 2024-10-02 15:25:36 +01:00
Tom Hvitved
6da3972433 Rust: Simplify break/continue CFG labels 2024-10-02 15:45:18 +02:00
Tom Hvitved
1266f9757d Rust: Add {BreakExpr,ContinueExpr}.getTarget() 2024-10-02 15:45:16 +02:00
Tom Hvitved
000dedf3e8 Rust: Output CFG for library-tests/variables 2024-10-02 15:45:14 +02:00
Michael Nebel
51623c3837 Java: Consider all summarized callable with generated verification as generated when counting generated vs manual. 2024-10-02 15:24:01 +02:00
Michael Nebel
104d448b16 Shared: Only use heuristic summary flow in case there is no content based flow. 2024-10-02 15:24:01 +02:00
Chad Bentz
2458d16426 Clarify threat model flow sources comment in LogForgingQuery.qll 2024-10-01 23:04:22 -04:00
Ed Minnix
f8335e6163 Fix formatting 2024-10-01 15:58:07 -04:00
Edward Minnix III
91b7a6cbd8 Wording of change note
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-10-01 15:56:43 -04:00
Edward Minnix III
1f932d407f Remove unnecessary asExpr()
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-10-01 15:56:42 -04:00
Ed Minnix
26b49dd0df Fix test expectation 2024-10-01 15:56:40 -04:00
Ed Minnix
d80a1487be Add change note 2024-10-01 15:56:37 -04:00
Ed Minnix
e18389718c Implement stdin models
Unfortunately due to how variable and varargs work, these are better
done in QL
2024-10-01 15:56:31 -04:00
Angela P Wen
e8dd6a88e7 Revert "Release preparation for version 2.19.1" 2024-10-01 10:19:28 -07:00
Chris Smowton
6ef2aed3aa Add blackbox, out-of-package test 2024-10-01 15:52:30 +01:00
Chris Smowton
9a82ea48f2 Add test for cross-package references with test extraction 2024-10-01 15:50:43 +01:00
Rasmus Lerchedahl Petersen
315890680c Python: dict only has one positional argument 2024-10-01 16:48:43 +02:00
Rasmus Lerchedahl Petersen
38b1eb7c71 Python: just use ListElementContent for iterables 2024-10-01 16:24:15 +02:00
Rasmus Lerchedahl Petersen
f39dc41903 Python: use imprecise content in cp
We had accidentally used precise content leadingto blowup
2024-10-01 13:53:25 +02:00
Rasmus Lerchedahl Petersen
05910de8d1 Python: MaD expectations 2024-10-01 13:21:22 +02:00
Rasmus Lerchedahl Petersen
cef8744a37 Python: consolidate models in one file 2024-10-01 12:56:21 +02:00
yoff
7816f34d75 Merge branch 'main' into stdlib-optparse 2024-10-01 12:48:09 +02:00
Rasmus Lerchedahl Petersen
64890a1a6b Python: valid change note 2024-10-01 12:37:45 +02:00
yoff
2b6aab108d Update python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll
Co-authored-by: Taus <tausbn@github.com>
2024-10-01 12:36:20 +02:00
yoff
2eac11edd6 Update python/ql/lib/change-notes/2024-09-24-std-lib-models.md
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-10-01 11:47:42 +02:00
yoff
62509a10c2 Update python/ql/test/library-tests/dataflow/coverage/test_builtins.py
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-10-01 11:39:12 +02:00
Rasmus Lerchedahl Petersen
e0a3c8a1c4 Python: add change note 2024-10-01 10:12:39 +02:00
Rasmus Lerchedahl Petersen
bd68986fa4 Python: add test showing dict can take multiple arguments 2024-10-01 10:01:22 +02:00
Rasmus Lerchedahl Petersen
9357762e06 Python: remove superflous code
This is handled by parameter-argument matching
2024-10-01 00:03:04 +02:00
Rasmus Lerchedahl Petersen
dacc0ab8fe Python: docs and a simplification 2024-09-30 16:06:30 +02:00
Rasmus Lerchedahl Petersen
438e664116 Python: add missing qldoc
More doc is needed, but this should turn the tests green
2024-09-30 15:43:19 +02:00
Rasmus Lerchedahl Petersen
a22ea6c1c8 Python: use known sanitiser
- also adjust test expectations in experimental
2024-09-30 14:22:17 +02:00
Rasmus Lerchedahl Petersen
7392d186bc Python: use yield step also for taint
Using the comprehension store step meant that all comprehensions would receive taint.
This because comprehension flow now goes via a callable, meaning they share the return node.
2024-09-30 13:49:01 +02:00
Rasmus Lerchedahl Petersen
fb07a56de6 Python: adjust test expectations 2024-09-30 13:26:59 +02:00
Rasmus Lerchedahl Petersen
ded39749a7 Python: allow comp arg as argumentnode 2024-09-30 13:02:20 +02:00
Rasmus Lerchedahl Petersen
f9f46f0f98 Python: update test expectations
We now have a new callable, yielding new enclosing callables
2024-09-30 12:00:38 +02:00
Rasmus Lerchedahl Petersen
3ef05a628f Python: add location to node 2024-09-30 11:56:36 +02:00
Rasmus Lerchedahl Petersen
310819d392 Python: fix dataflow inconsistencies
- adjust scope of argument, the argument is outside the called function
- add missing post-update nodes for the new arguments
2024-09-30 10:31:36 +02:00
Rasmus Lerchedahl Petersen
d4ea62edec Python: flow through yield
- add yield as a dataflow return
- replace comprehension store step
   with a store step to the yield
2024-09-30 09:01:29 +02:00
Arthur Baars
7c6239b077 Merge branch 'main' into unreachable 2024-09-27 12:15:49 +02:00
Rasmus Lerchedahl Petersen
72530a8312 Python: use synthetic node for comprehension capture argument
We used to use the CfgNode for the comprehension itself.
In cases where that is also an argument, say
```python
",".join([x for x in l])
```
that would be an argument to two different calls causing a dataflow consistency violation.
2024-09-27 12:15:03 +02:00
Rasmus Lerchedahl Petersen
294092b671 Python: use comprehension function argument
For a comprehension `[x for x in l]
- `l` is now a legal argument (in DataFlowPublic)
- `l` is the argument of the comprehension function (in DataFlowDispatch)
- the parameter of the comprehension function is being read rather than `l` (in IterableUnpacking)
Thus the read that used to cross callable boundaries is now split into a arg-param edge and a read from that param.
2024-09-27 09:44:39 +02:00
Rasmus Lerchedahl Petersen
fc2dc28f87 python: capture flow through comprehensions
- add comprehension functions as `DataFlowCallable`s
- add comprehension call as `DataFlowCall`
- create capture argument node for comprehension calls
2024-09-25 10:02:31 +02:00
Rasmus Lerchedahl Petersen
112e7c95fa Python: all dict constructor args are relevant 2024-09-24 20:58:59 +02:00
yoff
e7f9b5bbbc Merge branch 'main' into stdlib-optparse 2024-09-24 20:24:00 +02:00
Rasmus Lerchedahl Petersen
f95926e1a8 Python: add change note 2024-09-24 20:23:39 +02:00
Geoffrey White
3e0d30f13a Rust: Merge of unusedvar and unreachable work. 2024-09-20 12:58:38 +01:00
Geoffrey White
58b9355c69 Merge branch 'main' into unreachable 2024-09-20 12:53:49 +01:00
Geoffrey White
1eaa998648 Rust: Implement unreachable code query. 2024-09-19 17:44:15 +01:00
Geoffrey White
e7e0c6bf12 Rust: Add qhelp + examples for unreachable code query. 2024-09-19 17:34:46 +01:00
Geoffrey White
35378aa714 Rust: Add placeholder query + test for unreachable code query. 2024-09-19 17:34:41 +01:00
Rasmus Lerchedahl Petersen
3434c38da7 Python: update test expectations
This is MaD...
2024-07-22 17:03:29 +02:00
Rasmus Lerchedahl Petersen
e30f725e71 Python: Remove questionable model for multiprocessing.connection.Listener 2024-07-22 15:43:06 +02:00
Rasmus Lerchedahl Petersen
e40ae2e52d Python: adjust test expectations
MaD row numbers in provenance column
2024-06-28 21:56:11 +02:00
Rasmus Lerchedahl Petersen
77a00873a9 Python: add tests for loggers 2024-06-28 15:25:17 +02:00
Rasmus Lerchedahl Petersen
5ddfe75a0d Python: Add value steps for sequence elements
It would be nice to simplify to a single sequence content type..
2024-06-28 15:10:08 +02:00
Rasmus Lerchedahl Petersen
59f953269a Python: remove strange sink
It is not clear from the code how this could happen and
I do not remember the path I saw, perhaps it was unreasonable.
2024-06-28 14:42:24 +02:00
yoff
bbc3ff2dfe Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-06-28 14:39:03 +02:00
Rasmus Lerchedahl Petersen
a3076f4f72 Python: fix test expectations, add missing sanitizer 2024-06-26 13:27:32 +02:00
Rasmus Lerchedahl Petersen
b261145f43 Python: fix compilation 2024-06-26 10:46:38 +02:00
Rasmus Lerchedahl Petersen
571be8be3e Python: model more loggers 2024-06-26 01:00:38 +02:00
Rasmus Lerchedahl Petersen
eb32cbe8a5 Python: codecs.open 2024-06-26 00:57:59 +02:00
Rasmus Lerchedahl Petersen
bdc48088e6 Python: MaD summary models
Two of the generated summaries have been excluded:
 - ["re", "Member[split]", "Argument[0,pattern:]", "ReturnValue", "taint"]
   From the documentation, it is not clear why pattern should figure in the return value, as that is the part denoting split point and thus all those instances are filtered out.
   From the implementation
     Spit function: https://github.com/python/cpython/blob/3.12/Lib/re/__init__.py#L199
     _compile function being called by split: https://github.com/python/cpython/blob/3.12/Lib/re/__init__.py#L280
   We see that in case the pattern is already a compiled `Pattern`, it is returned directly from _compile and could thus be part of the return value from split. This is probably not possible to arrange for an attacker, and so an FP in practice.

 - ["urllib2", "Member[unquote]", "Argument[0,string:]", "ReturnValue", "taint"]
   urllib2 seems to be only in Python2 (e.g. https://docs.python.org/2.7/library/urllib2.html) and I cannot locate the function unquote.
2024-06-26 00:39:30 +02:00
Rasmus Lerchedahl Petersen
bc551174f9 Python: model copy.deepcopy as a value step 2024-06-25 14:53:06 +02:00
Rasmus Lerchedahl Petersen
501cda4e8c Python: model fnmatch.filter 2024-06-25 14:44:39 +02:00
Rasmus Lerchedahl Petersen
2118f233b9 Python: model optparse.OptionParser.parse_arg 2024-06-25 14:40:23 +02:00
Rasmus Lerchedahl Petersen
b80a711b27 python: undo changes to qlpack 2024-06-25 14:13:59 +02:00
Rasmus Lerchedahl Petersen
1e97600c4a Python: move models 2024-06-25 14:13:56 +02:00
Rasmus Lerchedahl Petersen
d410136852 python: compress models 2024-06-25 14:13:52 +02:00
Rasmus Lerchedahl Petersen
c004ffaca8 python: move model to Stdlib.yml
There is already a model there so we add to that one.

We did observe that this existing model was blocked by the external MaD model.
This is concerning and needs to be cleared up.
2024-06-25 14:13:48 +02:00
Rasmus Lerchedahl Petersen
281ac05868 python: add modelling for urlib.parse
- `quote` together with `re.compile` recover regex injection alerts on haiwen/seahub
- `quote_plus` recovers the URL redirection alert on DemocracyClub/EveryElection
- `unquote` recovers path injection alerts on `cloudera/hue`
- it was tedious finding justifications for the rest..
2024-06-25 14:13:44 +02:00
Rasmus Lerchedahl Petersen
df406b4fca python: Start modelling using MaD
- empty models for now
- `summaryModel` of `codeql/python-all` will be added to shortly.
2024-06-25 14:13:41 +02:00
596 changed files with 34174 additions and 10638 deletions

View File

@@ -25,5 +25,6 @@ common --registry=https://bcr.bazel.build
common --@rules_dotnet//dotnet/settings:strict_deps=false
common --experimental_isolated_extension_usages
common --incompatible_use_plus_in_repo_names
try-import %workspace%/local.bazelrc

22
Cargo.lock generated
View File

@@ -112,6 +112,16 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "ast-generator"
version = "0.1.0"
dependencies = [
"itertools 0.10.5",
"proc-macro2",
"quote",
"ungrammar",
]
[[package]]
name = "atomic"
version = "0.6.0"
@@ -380,11 +390,13 @@ dependencies = [
"ra_ap_base_db",
"ra_ap_hir",
"ra_ap_hir_def",
"ra_ap_hir_expand",
"ra_ap_ide_db",
"ra_ap_load-cargo",
"ra_ap_parser",
"ra_ap_paths",
"ra_ap_project_model",
"ra_ap_span",
"ra_ap_syntax",
"ra_ap_vfs",
"rust-extractor-macros",
@@ -681,16 +693,6 @@ version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
[[package]]
name = "generate-schema"
version = "0.1.0"
dependencies = [
"itertools 0.10.5",
"proc-macro2",
"quote",
"ungrammar",
]
[[package]]
name = "getrandom"
version = "0.2.15"

View File

@@ -7,7 +7,7 @@ members = [
"ruby/extractor",
"rust/extractor",
"rust/extractor/macros",
"rust/generate-schema",
"rust/ast-generator",
]
[patch.crates-io]

View File

@@ -23,11 +23,11 @@ bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "abseil-cpp", version = "20240116.0", 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 = "1.9.4-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1")
bazel_dep(name = "gazelle", version = "0.38.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.50.0")
bazel_dep(name = "rules_rust", version = "0.52.2")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
@@ -61,7 +61,7 @@ r.from_cargo(
"//ruby/extractor:Cargo.toml",
"//rust/extractor:Cargo.toml",
"//rust/extractor/macros:Cargo.toml",
"//rust/generate-schema:Cargo.toml",
"//rust/ast-generator:Cargo.toml",
"//shared/tree-sitter-extractor:Cargo.toml",
],
)

View File

@@ -0,0 +1,15 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprRequires(Expr expr) { exists(int kind | exprs(expr, kind, _) | kind = 390) }
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprRequires(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add requires expr
compatibility: partial
exprs.rel: run exprs.qlo

View File

@@ -1,3 +1,10 @@
## 2.0.2
### Minor Analysis Improvements
* Added taint flow model for `fopen` and related functions.
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.
## 2.0.1
No user-facing changes.

View File

@@ -0,0 +1,6 @@
## 2.0.2
### Minor Analysis Improvements
* Added taint flow model for `fopen` and related functions.
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.0.1
lastReleaseVersion: 2.0.2

View File

@@ -17,6 +17,7 @@ import semmle.code.cpp.File
import semmle.code.cpp.Linkage
import semmle.code.cpp.Location
import semmle.code.cpp.Compilation
import semmle.code.cpp.Concept
import semmle.code.cpp.Element
import semmle.code.cpp.Namespace
import semmle.code.cpp.Specifier

View File

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

View File

@@ -0,0 +1,14 @@
/**
* Provides classes for working with C++ concepts.
*/
import semmle.code.cpp.exprs.Expr
/**
* A C++ requires expression.
*/
class RequiresExpr extends Expr, @requires_expr {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "RequiresExpr" }
}

View File

@@ -80,6 +80,8 @@ private Declaration getAnEnclosingDeclaration(Locatable ast) {
or
result = ast.(Parameter).getFunction()
or
result = ast.(Parameter).getCatchBlock().getEnclosingFunction()
or
result = ast.(Expr).getEnclosingDeclaration()
or
result = ast.(Initializer).getDeclaration()
@@ -510,6 +512,22 @@ class DeclStmtNode extends StmtNode {
}
}
/**
* A node representing a `Handler`.
*/
class HandlerNode extends ChildStmtNode {
Handler handler;
HandlerNode() { handler = stmt }
override BaseAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
childIndex = -1 and
result.getAst() = handler.getParameter()
}
}
/**
* A node representing a `Parameter`.
*/
@@ -754,6 +772,8 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
or
s.(Handler).getParameter() = e and pred = "getParameter()"
or
s.(IfStmt).getInitialization() = e and pred = "getInitialization()"
or
s.(IfStmt).getCondition() = e and pred = "getCondition()"

View File

@@ -6,6 +6,112 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump.
*
* Anatomy of a printed IR instruction
*
* An instruction:
*
* ```
* # 2281| v2281_19(void) = Call[~String] : func:r2281_18, this:r2281_17
* ```
*
* The prefix `# 2281|` specifies that this instruction was generated by the C++ source code on line 2281.
* Scrolling up in the printed output, one will eventually find the name of the file to which the line
* belongs.
*
* `v2281_19(void)` is the result of the instruction. Here, `v` means this is a void result or operand (so
* there should be no later uses of the result; see below for other possible values). The `2281_19` is a
* unique ID for the result. This is usually just the line number plus a small integer suffix to make it
* unique within the function. The type of the result is `void`. In this case, it is `void`, because
* `~String` returns `void`. The type of the result is usually just the name of the appropriate C++ type,
* but it will sometimes be a type like `glval<int>`, which means result holds a glvalue, which at the
* IR level works like a pointer. In other words, in the source code the type was `int`, but it is really
* more like an `int*`. We see this, for example, in `x = y;`, where `x` is a glvalue.
*
* `Call` is the opcode of the instruction. Common opcodes include:
*
* * Arithmetic operations: `Add`, `Sub`, `Mul`, etc.
* * Memory access operations: `Load`, `Store`.
* * Function calls: `Call`.
* * Literals: `Constant`.
* * Variable addresses: `VariableAddress`.
* * Function entry points: `EnterFunction`.
* * Return from a function: `Return`, `ReturnVoid`. Note that the value being returned is set separately by a
* `Store` to a special `#return` variable.
* * Stack unwinding for C++ function that throw and where the exception escapes the function: `Unwind`.
* * Common exit point for `Unwind` and `Return`: `ExitFunction`.
* * SSA-related opcodes: `Phi`, `Chi`.
*
* `[~String]` denotes additional information. The information might be present earlier in the IR, as is the case
* for `Call`, where it is the name of the called function. This is also the case for `Load` and `Store`, where it
* is the name of the variable that loaded or stored (if known). In the case of `Constant`, `FieldAddress`, and
* `VariableAddress`, the information between brackets does not occur earlier.
*
* `func:r2281_18` and `this:r28281_17` are the operands of the instruction. The `func:` prefix denotes the operand
* that holds the address of the called function. The `this:` prefix denotes the argument to the special `this`
* parameter of an instance member function. `r2281_18`, `r2281_17` are the unique IDs of the operands. Each of these
* matches the ID of a previously seen result, showing where that value came from. The `r` means that these are
* "register" operands (see below).
*
* Result and operand kinds:
*
* Every result and operand is one of these three kinds:
*
* * `r` "register". These operands are not stored in any particular memory location. We can think of them as
* temporary values created during the evaluation of an expression. A register operand almost always has one
* use, often in the same block as its definition.
* * `m` "memory". These operands represents accesses to a specific memory location. The location could be a
* local variable, a global variable, a field of an object, an element of an array, or any memory that we happen
* to have a pointer to. These only occur as the result of a `Store`, the source operand of a `Load` or on the
* SSA instructions (`Phi`, `Chi`).
* * `v` "void". Really just a register operand, but we mark register operands of type void with this special prefix
* so we know that there is no actual value there.
*
* Branches in the IR:
*
* The IR is divided into basic blocks. At the end of each block, there are one or more edges showing the possible
* control flow successors of the block.
*
* ```
* # 44| v44_3(void) = ConditionalBranch : r44_2
* #-----| False -> Block 4
* #-----| True -> Block 3
* ```
* Here we have a block that ends with a conditional branch. The two edges show where the control flows to depending
* on whether the condition is true or false.
*
* SSA instructions:
*
* We use `Phi` instructions in SSA to create a single definition for a variable that might be assigned on multiple
* control flow paths. The `Phi` instruction merges the potential values of that variable from each predecessor edge,
* and the resulting definition is then used wherever that variable is accessed later on.
*
* When dealing with aliased memory, we use the `Chi` instruction to create a single definition for memory that might
* or might not have been updated by a store, depending on the actual address that was written to. For example, take:
*
* ```cpp
* int x = 5;
* int y = 7;
* int* p = condition ? &x : &y;
* *p = 6;
* return x;
* ```
*
* At the point where we store to `*p`, we do not know whether `p` points to `x` or `y`. Thus, we do not know whether
* `return x;` is going to return the value that `x` was originally initialized to (5), or whether it will return 6,
* because it was overwritten by `*p = 6;`. We insert a `Chi` instruction immediately after the store to `*p`:
*
* ```
* r2(int) = Constant[6]
* r3(int*) = <<value of p>>
* m4(int) = Store : &r3, r2 // Stores the constant 6 to *p
* m5(unknown) = Chi : total:m1, partial:m4
* ```
* The `partial:` operand represents the memory that was just stored. The `total:` operand represents the previous
* contents of all of the memory that `p` might have pointed to (in this case, both `x` and `y`). The result of the
* `Chi` represents the new contents of whatever memory the `total:` operand referred to. We usually do not know exactly
* which parts of that memory were overwritten, but it does model that any of that memory could have been modified, so
* that later instructions do not assume that the memory was unchanged.
*/
private import internal.IRInternal

View File

@@ -6,6 +6,112 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump.
*
* Anatomy of a printed IR instruction
*
* An instruction:
*
* ```
* # 2281| v2281_19(void) = Call[~String] : func:r2281_18, this:r2281_17
* ```
*
* The prefix `# 2281|` specifies that this instruction was generated by the C++ source code on line 2281.
* Scrolling up in the printed output, one will eventually find the name of the file to which the line
* belongs.
*
* `v2281_19(void)` is the result of the instruction. Here, `v` means this is a void result or operand (so
* there should be no later uses of the result; see below for other possible values). The `2281_19` is a
* unique ID for the result. This is usually just the line number plus a small integer suffix to make it
* unique within the function. The type of the result is `void`. In this case, it is `void`, because
* `~String` returns `void`. The type of the result is usually just the name of the appropriate C++ type,
* but it will sometimes be a type like `glval<int>`, which means result holds a glvalue, which at the
* IR level works like a pointer. In other words, in the source code the type was `int`, but it is really
* more like an `int*`. We see this, for example, in `x = y;`, where `x` is a glvalue.
*
* `Call` is the opcode of the instruction. Common opcodes include:
*
* * Arithmetic operations: `Add`, `Sub`, `Mul`, etc.
* * Memory access operations: `Load`, `Store`.
* * Function calls: `Call`.
* * Literals: `Constant`.
* * Variable addresses: `VariableAddress`.
* * Function entry points: `EnterFunction`.
* * Return from a function: `Return`, `ReturnVoid`. Note that the value being returned is set separately by a
* `Store` to a special `#return` variable.
* * Stack unwinding for C++ function that throw and where the exception escapes the function: `Unwind`.
* * Common exit point for `Unwind` and `Return`: `ExitFunction`.
* * SSA-related opcodes: `Phi`, `Chi`.
*
* `[~String]` denotes additional information. The information might be present earlier in the IR, as is the case
* for `Call`, where it is the name of the called function. This is also the case for `Load` and `Store`, where it
* is the name of the variable that loaded or stored (if known). In the case of `Constant`, `FieldAddress`, and
* `VariableAddress`, the information between brackets does not occur earlier.
*
* `func:r2281_18` and `this:r28281_17` are the operands of the instruction. The `func:` prefix denotes the operand
* that holds the address of the called function. The `this:` prefix denotes the argument to the special `this`
* parameter of an instance member function. `r2281_18`, `r2281_17` are the unique IDs of the operands. Each of these
* matches the ID of a previously seen result, showing where that value came from. The `r` means that these are
* "register" operands (see below).
*
* Result and operand kinds:
*
* Every result and operand is one of these three kinds:
*
* * `r` "register". These operands are not stored in any particular memory location. We can think of them as
* temporary values created during the evaluation of an expression. A register operand almost always has one
* use, often in the same block as its definition.
* * `m` "memory". These operands represents accesses to a specific memory location. The location could be a
* local variable, a global variable, a field of an object, an element of an array, or any memory that we happen
* to have a pointer to. These only occur as the result of a `Store`, the source operand of a `Load` or on the
* SSA instructions (`Phi`, `Chi`).
* * `v` "void". Really just a register operand, but we mark register operands of type void with this special prefix
* so we know that there is no actual value there.
*
* Branches in the IR:
*
* The IR is divided into basic blocks. At the end of each block, there are one or more edges showing the possible
* control flow successors of the block.
*
* ```
* # 44| v44_3(void) = ConditionalBranch : r44_2
* #-----| False -> Block 4
* #-----| True -> Block 3
* ```
* Here we have a block that ends with a conditional branch. The two edges show where the control flows to depending
* on whether the condition is true or false.
*
* SSA instructions:
*
* We use `Phi` instructions in SSA to create a single definition for a variable that might be assigned on multiple
* control flow paths. The `Phi` instruction merges the potential values of that variable from each predecessor edge,
* and the resulting definition is then used wherever that variable is accessed later on.
*
* When dealing with aliased memory, we use the `Chi` instruction to create a single definition for memory that might
* or might not have been updated by a store, depending on the actual address that was written to. For example, take:
*
* ```cpp
* int x = 5;
* int y = 7;
* int* p = condition ? &x : &y;
* *p = 6;
* return x;
* ```
*
* At the point where we store to `*p`, we do not know whether `p` points to `x` or `y`. Thus, we do not know whether
* `return x;` is going to return the value that `x` was originally initialized to (5), or whether it will return 6,
* because it was overwritten by `*p = 6;`. We insert a `Chi` instruction immediately after the store to `*p`:
*
* ```
* r2(int) = Constant[6]
* r3(int*) = <<value of p>>
* m4(int) = Store : &r3, r2 // Stores the constant 6 to *p
* m5(unknown) = Chi : total:m1, partial:m4
* ```
* The `partial:` operand represents the memory that was just stored. The `total:` operand represents the previous
* contents of all of the memory that `p` might have pointed to (in this case, both `x` and `y`). The result of the
* `Chi` represents the new contents of whatever memory the `total:` operand referred to. We usually do not know exactly
* which parts of that memory were overwritten, but it does model that any of that memory could have been modified, so
* that later instructions do not assume that the memory was unchanged.
*/
private import internal.IRInternal

View File

@@ -6,6 +6,112 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump.
*
* Anatomy of a printed IR instruction
*
* An instruction:
*
* ```
* # 2281| v2281_19(void) = Call[~String] : func:r2281_18, this:r2281_17
* ```
*
* The prefix `# 2281|` specifies that this instruction was generated by the C++ source code on line 2281.
* Scrolling up in the printed output, one will eventually find the name of the file to which the line
* belongs.
*
* `v2281_19(void)` is the result of the instruction. Here, `v` means this is a void result or operand (so
* there should be no later uses of the result; see below for other possible values). The `2281_19` is a
* unique ID for the result. This is usually just the line number plus a small integer suffix to make it
* unique within the function. The type of the result is `void`. In this case, it is `void`, because
* `~String` returns `void`. The type of the result is usually just the name of the appropriate C++ type,
* but it will sometimes be a type like `glval<int>`, which means result holds a glvalue, which at the
* IR level works like a pointer. In other words, in the source code the type was `int`, but it is really
* more like an `int*`. We see this, for example, in `x = y;`, where `x` is a glvalue.
*
* `Call` is the opcode of the instruction. Common opcodes include:
*
* * Arithmetic operations: `Add`, `Sub`, `Mul`, etc.
* * Memory access operations: `Load`, `Store`.
* * Function calls: `Call`.
* * Literals: `Constant`.
* * Variable addresses: `VariableAddress`.
* * Function entry points: `EnterFunction`.
* * Return from a function: `Return`, `ReturnVoid`. Note that the value being returned is set separately by a
* `Store` to a special `#return` variable.
* * Stack unwinding for C++ function that throw and where the exception escapes the function: `Unwind`.
* * Common exit point for `Unwind` and `Return`: `ExitFunction`.
* * SSA-related opcodes: `Phi`, `Chi`.
*
* `[~String]` denotes additional information. The information might be present earlier in the IR, as is the case
* for `Call`, where it is the name of the called function. This is also the case for `Load` and `Store`, where it
* is the name of the variable that loaded or stored (if known). In the case of `Constant`, `FieldAddress`, and
* `VariableAddress`, the information between brackets does not occur earlier.
*
* `func:r2281_18` and `this:r28281_17` are the operands of the instruction. The `func:` prefix denotes the operand
* that holds the address of the called function. The `this:` prefix denotes the argument to the special `this`
* parameter of an instance member function. `r2281_18`, `r2281_17` are the unique IDs of the operands. Each of these
* matches the ID of a previously seen result, showing where that value came from. The `r` means that these are
* "register" operands (see below).
*
* Result and operand kinds:
*
* Every result and operand is one of these three kinds:
*
* * `r` "register". These operands are not stored in any particular memory location. We can think of them as
* temporary values created during the evaluation of an expression. A register operand almost always has one
* use, often in the same block as its definition.
* * `m` "memory". These operands represents accesses to a specific memory location. The location could be a
* local variable, a global variable, a field of an object, an element of an array, or any memory that we happen
* to have a pointer to. These only occur as the result of a `Store`, the source operand of a `Load` or on the
* SSA instructions (`Phi`, `Chi`).
* * `v` "void". Really just a register operand, but we mark register operands of type void with this special prefix
* so we know that there is no actual value there.
*
* Branches in the IR:
*
* The IR is divided into basic blocks. At the end of each block, there are one or more edges showing the possible
* control flow successors of the block.
*
* ```
* # 44| v44_3(void) = ConditionalBranch : r44_2
* #-----| False -> Block 4
* #-----| True -> Block 3
* ```
* Here we have a block that ends with a conditional branch. The two edges show where the control flows to depending
* on whether the condition is true or false.
*
* SSA instructions:
*
* We use `Phi` instructions in SSA to create a single definition for a variable that might be assigned on multiple
* control flow paths. The `Phi` instruction merges the potential values of that variable from each predecessor edge,
* and the resulting definition is then used wherever that variable is accessed later on.
*
* When dealing with aliased memory, we use the `Chi` instruction to create a single definition for memory that might
* or might not have been updated by a store, depending on the actual address that was written to. For example, take:
*
* ```cpp
* int x = 5;
* int y = 7;
* int* p = condition ? &x : &y;
* *p = 6;
* return x;
* ```
*
* At the point where we store to `*p`, we do not know whether `p` points to `x` or `y`. Thus, we do not know whether
* `return x;` is going to return the value that `x` was originally initialized to (5), or whether it will return 6,
* because it was overwritten by `*p = 6;`. We insert a `Chi` instruction immediately after the store to `*p`:
*
* ```
* r2(int) = Constant[6]
* r3(int*) = <<value of p>>
* m4(int) = Store : &r3, r2 // Stores the constant 6 to *p
* m5(unknown) = Chi : total:m1, partial:m4
* ```
* The `partial:` operand represents the memory that was just stored. The `total:` operand represents the previous
* contents of all of the memory that `p` might have pointed to (in this case, both `x` and `y`). The result of the
* `Chi` represents the new contents of whatever memory the `total:` operand referred to. We usually do not know exactly
* which parts of that memory were overwritten, but it does model that any of that memory could have been modified, so
* that later instructions do not assume that the memory was unchanged.
*/
private import internal.IRInternal

View File

@@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/** The function `fopen` and friends. */
private class Fopen extends Function, AliasFunction, SideEffectFunction {
private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFunction {
Fopen() {
this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"])
or
@@ -47,4 +47,22 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction {
i = 0 and
buffer = true
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
(
this.hasGlobalOrStdName(["fopen", "freopen"]) or
this.hasGlobalName(["_wfopen", "_fsopen", "_wfsopen"])
) and
input.isParameterDeref(0) and
output.isReturnValueDeref()
or
// The out parameter is a pointer to a `FILE*`.
this.hasGlobalOrStdName("fopen_s") and
input.isParameterDeref(1) and
output.isParameterDeref(0, 2)
or
this.hasGlobalName(["_open", "_wopen"]) and
input.isParameterDeref(0) and
output.isReturnValue()
}
}

View File

@@ -192,6 +192,37 @@ private class UnsignedMulExpr extends MulExpr {
}
}
/**
* Gets the value of the `EOF` macro.
*
* This is typically `"-1"`, but this is not guaranteed to be the case on all
* systems.
*/
private int getEofValue() {
exists(MacroInvocation mi |
mi.getMacroName() = "EOF" and
result = unique( | | mi.getExpr().getValue().toInt())
)
}
/** Get standard `getc` function or related variants. */
private class Getc extends Function {
Getc() { this.hasGlobalOrStdOrBslName(["fgetc", "getc"]) }
}
/** A call to `getc` */
private class CallToGetc extends FunctionCall {
CallToGetc() { this.getTarget() instanceof Getc }
}
/**
* A call to `getc` that we can analyze because we know
* the value of the `EOF` macro.
*/
private class AnalyzableCallToGetc extends CallToGetc {
AnalyzableCallToGetc() { exists(getEofValue()) }
}
/**
* Holds if `expr` is effectively a multiplication of `operand` with the
* positive constant `positive`.
@@ -287,6 +318,8 @@ private predicate analyzableExpr(Expr e) {
or
e instanceof RemExpr
or
e instanceof AnalyzableCallToGetc
or
// A conversion is analyzable, provided that its child has an arithmetic
// type. (Sometimes the child is a reference type, and so does not get
// any bounds.) Rather than checking whether the type of the child is
@@ -861,6 +894,14 @@ private float getLowerBoundsImpl(Expr expr) {
)
)
or
exists(AnalyzableCallToGetc getc |
expr = getc and
// from https://en.cppreference.com/w/c/io/fgetc:
// On success, returns the obtained character as an unsigned char
// converted to an int. On failure, returns EOF.
result = min([typeLowerBound(any(UnsignedCharType pct)), getEofValue()])
)
or
// If the conversion is to an arithmetic type then we just return the
// lower bound of the child. We do not need to handle truncation and
// overflow here, because that is done in `getTruncatedLowerBounds`.
@@ -1055,6 +1096,14 @@ private float getUpperBoundsImpl(Expr expr) {
)
)
or
exists(AnalyzableCallToGetc getc |
expr = getc and
// from https://en.cppreference.com/w/c/io/fgetc:
// On success, returns the obtained character as an unsigned char
// converted to an int. On failure, returns EOF.
result = max([typeUpperBound(any(UnsignedCharType pct)), getEofValue()])
)
or
// If the conversion is to an arithmetic type then we just return the
// upper bound of the child. We do not need to handle truncation and
// overflow here, because that is done in `getTruncatedUpperBounds`.

View File

@@ -1790,6 +1790,7 @@ case @expr.kind of
| 387 = @istriviallyrelocatable
| 388 = @datasizeof
| 389 = @c11_generic
| 390 = @requires_expr
;
@var_args_expr = @vastartexpr

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add requires expressions
compatibility: full

View File

@@ -1,3 +1,12 @@
## 1.2.5
### Minor Analysis Improvements
* The `cpp/unclear-array-index-validation` ("Unclear validation of array index") query has been improved to reduce false positives and increase true positives.
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.
## 1.2.4
### Minor Analysis Improvements

View File

@@ -14,102 +14,56 @@
import cpp
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
import semmle.code.cpp.security.FlowSources as FS
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import ImproperArrayIndexValidation::PathGraph
import semmle.code.cpp.security.Security
predicate hasUpperBound(VariableAccess offsetExpr) {
exists(BasicBlock controlled, StackVariable offsetVar, SsaDefinition def |
controlled.contains(offsetExpr) and
linearBoundControls(controlled, def, offsetVar) and
offsetExpr = def.getAUse(offsetVar)
predicate isFlowSource(FS::FlowSource source, string sourceType) {
sourceType = source.getSourceType()
}
predicate guardChecks(IRGuardCondition g, Expr e, boolean branch) {
exists(Operand op | op.getDef().getConvertedResultExpression() = e |
// `op < k` is true and `k > 0`
g.comparesLt(op, any(int k | k > 0), true, any(BooleanValue bv | bv.getValue() = branch))
or
// `op < _ + k` is true and `k > 0`.
g.comparesLt(op, _, any(int k | k > 0), true, branch)
or
// op == k
g.comparesEq(op, _, true, any(BooleanValue bv | bv.getValue() = branch))
or
// op == _ + k
g.comparesEq(op, _, _, true, branch)
)
}
pragma[noinline]
predicate linearBoundControls(BasicBlock controlled, SsaDefinition def, StackVariable offsetVar) {
exists(GuardCondition guard, boolean branch |
guard.controls(controlled, branch) and
cmpWithLinearBound(guard, def.getAUse(offsetVar), Lesser(), branch)
/**
* Holds if `arrayExpr` accesses an `ArrayType` with a constant size `N`, and
* the value of `offsetExpr` is known to be smaller than `N`.
*/
predicate offsetIsAlwaysInBounds(ArrayExpr arrayExpr, VariableAccess offsetExpr) {
exists(ArrayType arrayType |
arrayType = arrayExpr.getArrayBase().getUnspecifiedType() and
arrayType.getArraySize() > upperBound(offsetExpr.getFullyConverted())
)
}
predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
readsVariable(node.asInstruction(), checkedVar) and
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
}
predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
predicate predictableInstruction(Instruction instr) {
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
or
// This could be a conversion on a string literal
predictableInstruction(instr.(UnaryInstruction).getUnary())
}
module ImproperArrayIndexValidationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
predicate isBarrier(DataFlow::Node node) {
hasUpperBound(node.asExpr())
or
// These barriers are ported from `DefaultTaintTracking` because this query is quite noisy
// otherwise.
exists(Variable checkedVar |
readsVariable(node.asInstruction(), checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
exists(Variable checkedVar, Operand access |
readsVariable(access.getDef(), checkedVar) and
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
)
or
// Don't use dataflow into binary instructions if both operands are unpredictable
exists(BinaryInstruction iTo |
iTo = node.asInstruction() and
not predictableInstruction(iTo.getLeft()) and
not predictableInstruction(iTo.getRight()) and
// propagate taint from either the pointer or the offset, regardless of predictability
not iTo instanceof PointerArithmeticInstruction
)
or
// don't use dataflow through calls to pure functions if two or more operands
// are unpredictable
exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
iTo = node.asInstruction() and
isPureFunction(iTo.getStaticCallTarget().getName()) and
iFrom1 = iTo.getAnArgument() and
iFrom2 = iTo.getAnArgument() and
not predictableInstruction(iFrom1) and
not predictableInstruction(iFrom2) and
iFrom1 != iFrom2
)
node = DataFlow::BarrierGuard<guardChecks/3>::getABarrierNode()
}
predicate isBarrierOut(DataFlow::Node node) { isSink(node) }
predicate isSink(DataFlow::Node sink) {
exists(ArrayExpr arrayExpr, VariableAccess offsetExpr |
offsetExpr = arrayExpr.getArrayOffset() and
sink.asExpr() = offsetExpr and
not hasUpperBound(offsetExpr)
not offsetIsAlwaysInBounds(arrayExpr, offsetExpr)
)
}
}

View File

@@ -1,5 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.

View File

@@ -0,0 +1,8 @@
## 1.2.5
### Minor Analysis Improvements
* The `cpp/unclear-array-index-validation` ("Unclear validation of array index") query has been improved to reduce false positives and increase true positives.
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.4
lastReleaseVersion: 1.2.5

View File

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

View File

@@ -870,6 +870,8 @@ Throw.cpp:
# 8| Type = [BoolType] bool
# 8| ValueCategory = prvalue
# 12| getChild(1): [Handler] <handler>
# 12| getParameter(): [Parameter] e
# 12| Type = [PointerType] E *
# 12| getBlock(): [CatchBlock] { ... }
# 13| getStmt(0): [ExprStmt] ExprStmt
# 13| getExpr(): [ReThrowExpr] re-throw exception

View File

@@ -6,7 +6,7 @@ int wprintf (const wchar_t* format, ...);
int strlen( const char * string );
int checkErrors();
void goodTest0()
static void goodTest0()
{
char * ptr = "123456789";
int ret;
@@ -17,7 +17,7 @@ void goodTest0()
ptr += ret;
}
}
void goodTest1(const char* ptr)
static void goodTest1(const char* ptr)
{
int ret;
int len;
@@ -27,7 +27,7 @@ void goodTest1(const char* ptr)
ptr += ret;
}
}
void goodTest2(char* ptr)
static void goodTest2(char* ptr)
{
int ret;
ptr[10]=0;
@@ -38,7 +38,7 @@ void goodTest2(char* ptr)
}
}
void goodTest3(const char* ptr)
static void goodTest3(const char* ptr)
{
int ret;
int len;
@@ -48,7 +48,7 @@ void goodTest3(const char* ptr)
ptr += ret;
}
}
void goodTest4(const char* ptr)
static void goodTest4(const char* ptr)
{
int ret;
int len;
@@ -58,7 +58,7 @@ void goodTest4(const char* ptr)
ptr += ret;
}
}
void badTest1(const char* ptr)
static void badTest1(const char* ptr)
{
int ret;
int len;
@@ -68,7 +68,7 @@ void badTest1(const char* ptr)
ptr += ret;
}
}
void badTest2(const char* ptr)
static void badTest2(const char* ptr)
{
int ret;
int len;
@@ -79,7 +79,7 @@ void badTest2(const char* ptr)
}
}
void goodTest5(const char* ptr,wchar_t *wc,int wc_len)
static void goodTest5(const char* ptr,wchar_t *wc,int wc_len)
{
int ret;
int len;
@@ -96,7 +96,7 @@ void goodTest5(const char* ptr,wchar_t *wc,int wc_len)
}
}
void badTest3(const char* ptr,int wc_len)
static void badTest3(const char* ptr,int wc_len)
{
int ret;
int len;
@@ -113,7 +113,7 @@ void badTest3(const char* ptr,int wc_len)
wc++;
}
}
void badTest4(const char* ptr,int wc_len)
static void badTest4(const char* ptr,int wc_len)
{
int ret;
int len;
@@ -130,7 +130,7 @@ void badTest4(const char* ptr,int wc_len)
wc++;
}
}
void badTest5(const char* ptr,int wc_len)
static void badTest5(const char* ptr,int wc_len)
{
int ret;
int len;
@@ -148,7 +148,7 @@ void badTest5(const char* ptr,int wc_len)
}
}
void badTest6(const char* ptr,int wc_len)
static void badTest6(const char* ptr,int wc_len)
{
int ret;
int len;
@@ -171,7 +171,7 @@ void badTest6(const char* ptr,int wc_len)
ptr+=ret;
}
}
void badTest7(const char* ptr,int wc_len)
static void badTest7(const char* ptr,int wc_len)
{
int ret;
int len;
@@ -188,7 +188,7 @@ void badTest7(const char* ptr,int wc_len)
ptr+=ret;
}
}
void badTest8(const char* ptr,wchar_t *wc)
static void badTest8(const char* ptr,wchar_t *wc)
{
int ret;
int len;

View File

@@ -24,7 +24,7 @@ typedef unsigned int size_t;
void* calloc (size_t num, size_t size);
void* malloc (size_t size);
void badTest1(void *src, int size) {
static void badTest1(void *src, int size) {
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, (LPSTR)src, size, 0, 0); // BAD
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, (LPCWSTR)src, 30); // BAD
}
@@ -39,43 +39,43 @@ void goodTest2(){
}
printf("%s\n", dst);
}
void badTest2(){
static void badTest2(){
wchar_t src[] = L"0123456789ABCDEF";
char dst[16];
WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // BAD
printf("%s\n", dst);
}
void goodTest3(){
static void goodTest3(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)calloc(size + 1, sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // GOOD
}
void badTest3(){
static void badTest3(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
}
void goodTest4(){
static void goodTest4(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)malloc((size + 1)*sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // GOOD
}
void badTest4(){
static void badTest4(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)malloc(size + 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
}
int goodTest5(void *src){
static int goodTest5(void *src){
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 0, 0, 0); // GOOD
}
int badTest5 (void *src) {
static int badTest5 (void *src) {
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 3, 0, 0); // BAD
}
void goodTest6(WCHAR *src)
static void goodTest6(WCHAR *src)
{
int size;
char dst[5] ="";
@@ -87,7 +87,7 @@ void goodTest6(WCHAR *src)
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, sizeof(dst), 0, 0); // GOOD
printf("%s\n", dst);
}
void badTest6(WCHAR *src)
static void badTest6(WCHAR *src)
{
char dst[5] ="";
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, 260, 0, 0); // BAD

View File

@@ -11,14 +11,14 @@ size_t _mbstowcs_l(wchar_t *wcstr,const char *mbstr,size_t count, _locale_t loca
size_t mbsrtowcs(wchar_t *wcstr,const char *mbstr,size_t count, mbstate_t *mbstate);
void badTest1(void *src, int size) {
static void badTest1(void *src, int size) {
mbstowcs((wchar_t*)src,(char*)src,size); // BAD
_locale_t locale;
_mbstowcs_l((wchar_t*)src,(char*)src,size,locale); // BAD
mbstate_t *mbstate;
mbsrtowcs((wchar_t*)src,(char*)src,size,mbstate); // BAD
}
void goodTest2(){
static void goodTest2(){
char src[] = "0123456789ABCDEF";
wchar_t dst[16];
int res = mbstowcs(dst, src,16); // GOOD
@@ -29,43 +29,43 @@ void goodTest2(){
}
printf("%s\n", dst);
}
void badTest2(){
static void badTest2(){
char src[] = "0123456789ABCDEF";
wchar_t dst[16];
mbstowcs(dst, src,16); // BAD
printf("%s\n", dst);
}
void goodTest3(){
static void goodTest3(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)calloc(size + 1, sizeof(wchar_t));
mbstowcs(dst, src,size+1); // GOOD
}
void badTest3(){
static void badTest3(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
mbstowcs(dst, src,size+1); // BAD
}
void goodTest4(){
static void goodTest4(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)malloc((size + 1)*sizeof(wchar_t));
mbstowcs(dst, src,size+1); // GOOD
}
void badTest4(){
static void badTest4(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)malloc(size + 1);
mbstowcs(dst, src,size+1); // BAD
}
int goodTest5(void *src){
static int goodTest5(void *src){
return mbstowcs(NULL, (char*)src,NULL); // GOOD
}
int badTest5 (void *src) {
static int badTest5 (void *src) {
return mbstowcs(NULL, (char*)src,3); // BAD
}
void goodTest6(void *src){
static void goodTest6(void *src){
wchar_t dst[5];
int size = mbstowcs(NULL, (char*)src,NULL);
if(size>=sizeof(dst)){
@@ -75,7 +75,7 @@ void goodTest6(void *src){
mbstowcs(dst, (char*)src,sizeof(dst)); // GOOD
printf("%s\n", dst);
}
void badTest6(void *src){
static void badTest6(void *src){
wchar_t dst[5];
mbstowcs(dst, (char*)src,260); // BAD
printf("%s\n", dst);

View File

@@ -9,14 +9,14 @@ void goodTest1(unsigned char *src){
unsigned char dst[50];
_mbsnbcpy(dst,src,sizeof(dst)); // GOOD
}
size_t badTest1(unsigned char *src){
static size_t badTest1(unsigned char *src){
int cb = 0;
unsigned char dst[50];
while( cb < sizeof(dst) )
dst[cb++]=*src++; // BAD
return _mbclen(dst);
}
void goodTest2(unsigned char *src){
static void goodTest2(unsigned char *src){
int cb = 0;
unsigned char dst[50];
@@ -27,7 +27,7 @@ void goodTest2(unsigned char *src){
src=_mbsinc(src);
}
}
void badTest2(unsigned char *src){
static void badTest2(unsigned char *src){
int cb = 0;
unsigned char dst[50];
@@ -38,11 +38,11 @@ void badTest2(unsigned char *src){
src=_mbsinc(src);
}
}
void goodTest3(){
static void goodTest3(){
wchar_t name[50];
name[sizeof(name) / sizeof(*name) - 1] = L'\0'; // GOOD
}
void badTest3(){
static void badTest3(){
wchar_t name[50];
name[sizeof(name) - 1] = L'\0'; // BAD
}

View File

@@ -78,7 +78,7 @@ int* deref(int** p) { // $ ast-def=p ir-def=*p ir-def=**p
return q;
}
void test1() {
void flowout_test1() {
int x = 0;
int* p = &x;
deref(&p)[0] = source();
@@ -95,7 +95,7 @@ void addtaint2(int** p) { // $ ast-def=p ir-def=*p ir-def=**p
addtaint1(q);
}
void test2() {
void flowout_test2() {
int x = 0;
int* p = &x;
addtaint2(&p);

View File

@@ -15,7 +15,7 @@ template<> struct std::iterator_traits<unsigned long>
};
int test() {
int iterator_test() {
unsigned long x = source();
sink(x); // $ ast ir
}

View File

@@ -5,7 +5,7 @@ int source();
void sink(...);
bool random();
void test1() {
void on_entry_test1() {
int x = source();
for (int i = 0; i < 10; i++) {
x = 0;
@@ -13,7 +13,7 @@ void test1() {
sink(x); // $ SPURIOUS: ir
}
void test2(int iterations) {
void on_entry_test2(int iterations) {
int x = source();
for (int i = 0; i < iterations; i++) {
x = 0;
@@ -21,7 +21,7 @@ void test2(int iterations) {
sink(x); // $ ast,ir
}
void test3() {
void on_entry_test3() {
int x = 0;
for (int i = 0; i < 10; i++) {
x = source();
@@ -29,7 +29,7 @@ void test3() {
sink(x); // $ ast,ir
}
void test4() {
void on_entry_test4() {
int x = source();
for (int i = 0; i < 10; i++) {
if (random())
@@ -39,7 +39,7 @@ void test4() {
sink(x); // $ ast,ir
}
void test5() {
void on_entry_test5() {
int x = source();
for (int i = 0; i < 10; i++) {
if (random())
@@ -49,7 +49,7 @@ void test5() {
sink(x); // $ ast,ir
}
void test6() {
void on_entry_test6() {
int y;
int x = source();
for (int i = 0; i < 10 && (y = 1); i++) {
@@ -57,7 +57,7 @@ void test6() {
sink(x); // $ ast,ir
}
void test7() {
void on_entry_test7() {
int y;
int x = source();
for (int i = 0; i < 10 && (y = 1); i++) {
@@ -66,7 +66,7 @@ void test7() {
sink(x); // $ SPURIOUS: ir
}
void test8() {
void on_entry_test8() {
int x = source();
// It appears to the analysis that the condition can exit after `i < 10`
// without having assigned to `x`. That is an effect of how the
@@ -78,7 +78,7 @@ void test8() {
sink(x); // $ SPURIOUS: ast,ir
}
void test9() {
void on_entry_test9() {
int y;
int x = source();
for (int i = 0; (y = 1) && i < 10; i++) {
@@ -86,14 +86,14 @@ void test9() {
sink(x); // $ ast,ir
}
void test10() {
void on_entry_test10() {
int x = source();
for (int i = 0; (x = 1) && i < 10; i++) {
}
sink(x); // no flow
}
void test10(int b, int d) {
void on_entry_test10(int b, int d) {
int i = 0;
int x = source();
if (b)

View File

@@ -6584,6 +6584,16 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| taint.cpp:767:21:767:24 | ref arg path | taint.cpp:768:8:768:11 | path | |
| taint.cpp:768:8:768:11 | path | taint.cpp:768:7:768:11 | * ... | |
| taint.cpp:778:37:778:42 | call to source | taint.cpp:779:7:779:9 | obj | |
| taint.cpp:785:23:785:28 | source | taint.cpp:785:23:785:28 | source | |
| taint.cpp:785:23:785:28 | source | taint.cpp:786:18:786:23 | source | |
| taint.cpp:785:23:785:28 | source | taint.cpp:790:15:790:20 | source | |
| taint.cpp:786:12:786:16 | call to fopen | taint.cpp:787:7:787:7 | f | |
| taint.cpp:786:18:786:23 | source | taint.cpp:786:12:786:16 | call to fopen | TAINT |
| taint.cpp:789:8:789:9 | f2 | taint.cpp:790:11:790:12 | f2 | |
| taint.cpp:789:8:789:9 | f2 | taint.cpp:791:7:791:8 | f2 | |
| taint.cpp:790:10:790:12 | ref arg & ... | taint.cpp:790:11:790:12 | f2 [inner post update] | |
| taint.cpp:790:10:790:12 | ref arg & ... | taint.cpp:791:7:791:8 | f2 | |
| taint.cpp:790:11:790:12 | f2 | taint.cpp:790:10:790:12 | & ... | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -777,4 +777,16 @@ TaintInheritingContentObject source(bool);
void test_TaintInheritingContent() {
TaintInheritingContentObject obj = source(true);
sink(obj.flowFromObject); // $ ir MISSING: ast
}
FILE* fopen(const char*, const char*);
int fopen_s(FILE** pFile, const char *filename, const char *mode);
void fopen_test(char* source) {
FILE* f = fopen(source, "r");
sink(f); // $ ast,ir
FILE* f2;
fopen_s(&f2, source, "r");
sink(f2); // $ ast,ir
}

View File

@@ -1,4 +1,4 @@
| c.c | library-tests/files/c.c | CFile, MetricFile | C | | |
| files1.cpp | library-tests/files/files1.cpp | CppFile, MetricFile | C++ | swap | t |
| files1.h | library-tests/files/files1.h | HeaderFile, MetricFile | | swap | |
| files2.cpp | library-tests/files/files2.cpp | CppFile, MetricFile | C++ | g | x, y |
| c.c | c.c | CFile, MetricFile | C | | |
| files1.cpp | files1.cpp | CppFile, MetricFile | C++ | swap | t |
| files1.h | files1.h | HeaderFile, MetricFile | | swap | |
| files2.cpp | files2.cpp | CppFile, MetricFile | C++ | g | x, y |

View File

@@ -9055,6 +9055,8 @@ ir.cpp:
# 733| Value = [Literal] 7
# 733| ValueCategory = prvalue
# 735| getChild(1): [Handler] <handler>
# 735| getParameter(): [Parameter] s
# 735| Type = [PointerType] const char *
# 735| getBlock(): [CatchBlock] { ... }
# 736| getStmt(0): [ExprStmt] ExprStmt
# 736| getExpr(): [ThrowExpr] throw ...
@@ -9067,6 +9069,8 @@ ir.cpp:
# 736| Type = [PointerType] const char *
# 736| ValueCategory = prvalue(load)
# 738| getChild(2): [Handler] <handler>
# 738| getParameter(): [Parameter] e
# 738| Type = [LValueReferenceType] const String &
# 738| getBlock(): [CatchBlock] { ... }
# 740| getChild(3): [Handler] <handler>
# 740| getBlock(): [CatchAnyBlock] { ... }
@@ -12852,6 +12856,8 @@ ir.cpp:
# 1200| Value = [Literal] 7
# 1200| ValueCategory = prvalue
# 1202| getChild(1): [Handler] <handler>
# 1202| getParameter(): [Parameter] s
# 1202| Type = [PointerType] const char *
# 1202| getBlock(): [CatchBlock] { ... }
# 1203| getStmt(0): [ExprStmt] ExprStmt
# 1203| getExpr(): [ThrowExpr] throw ...
@@ -12864,6 +12870,8 @@ ir.cpp:
# 1203| Type = [PointerType] const char *
# 1203| ValueCategory = prvalue(load)
# 1205| getChild(2): [Handler] <handler>
# 1205| getParameter(): [Parameter] e
# 1205| Type = [LValueReferenceType] const String &
# 1205| getBlock(): [CatchBlock] { ... }
# 1207| getStmt(1): [ReturnStmt] return ...
# 1211| [TopLevelFunction] void VectorTypes(int)
@@ -20586,6 +20594,8 @@ ir.cpp:
# 2281| Type = [Struct] String
# 2281| ValueCategory = lvalue
# 2282| getChild(1): [Handler] <handler>
# 2282| getParameter(): [Parameter] s
# 2282| Type = [PointerType] const char *
# 2282| getBlock(): [CatchBlock] { ... }
# 2283| getStmt(0): [ExprStmt] ExprStmt
# 2283| getExpr(): [ThrowExpr] throw ...
@@ -20598,6 +20608,8 @@ ir.cpp:
# 2283| Type = [PointerType] const char *
# 2283| ValueCategory = prvalue(load)
# 2285| getChild(2): [Handler] <handler>
# 2285| getParameter(): [Parameter] e
# 2285| Type = [LValueReferenceType] const String &
# 2285| getBlock(): [CatchBlock] { ... }
# 2287| getChild(3): [Handler] <handler>
# 2287| getBlock(): [CatchAnyBlock] { ... }
@@ -22845,6 +22857,8 @@ ir.cpp:
# 2537| Value = [Literal] 42
# 2537| ValueCategory = prvalue
# 2539| getChild(1): [Handler] <handler>
# 2539| getParameter(): [Parameter] (unnamed parameter 0)
# 2539| Type = [PlainCharType] char
# 2539| getBlock(): [CatchBlock] { ... }
# 2541| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
# 2541| Type = [VoidType] void
@@ -23564,6 +23578,26 @@ ir.cpp:
# 2686| Value = [CStyleCast] 0
# 2686| ValueCategory = prvalue
# 2687| getStmt(1): [ReturnStmt] return ...
# 2691| [TopLevelFunction] int concepts::requires_use()
# 2691| <params>:
# 2691| getEntryPoint(): [BlockStmt] { ... }
# 2692| getStmt(0): [DeclStmt] declaration
# 2692| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 2692| Type = [IntType] int
# 2692| getVariable().getInitializer(): [Initializer] initializer for y
#-----| getExpr(): [RequiresExpr] requires ...
#-----| Type = [BoolType] bool
#-----| Value = [RequiresExpr] 1
#-----| ValueCategory = prvalue
#-----| getExpr().getFullyConverted(): [CStyleCast] (int)...
#-----| Conversion = [IntegralConversion] integral conversion
#-----| Type = [IntType] int
#-----| Value = [CStyleCast] 1
#-----| ValueCategory = prvalue
# 2693| getStmt(1): [ReturnStmt] return ...
# 2693| getExpr(): [VariableAccess] y
# 2693| Type = [IntType] int
# 2693| ValueCategory = prvalue(load)
many-defs-per-use.cpp:
# 34| [TopLevelFunction] void many_defs_per_use()
# 34| <params>:

View File

@@ -19099,6 +19099,24 @@ ir.cpp:
# 2684| Block 8
# 2684| v2684_14(void) = Unreached :
# 2691| int concepts::requires_use()
# 2691| Block 0
# 2691| v2691_1(void) = EnterFunction :
# 2691| m2691_2(unknown) = AliasedDefinition :
# 2691| m2691_3(unknown) = InitializeNonLocal :
# 2691| m2691_4(unknown) = Chi : total:m2691_2, partial:m2691_3
# 2692| r2692_1(glval<int>) = VariableAddress[y] :
#-----| r0_1(int) = Constant[1] :
#-----| m0_2(int) = Store[y] : &:r2692_1, r0_1
# 2693| r2693_1(glval<int>) = VariableAddress[#return] :
# 2693| r2693_2(glval<int>) = VariableAddress[y] :
# 2693| r2693_3(int) = Load[y] : &:r2693_2, m0_2
# 2693| m2693_4(int) = Store[#return] : &:r2693_1, r2693_3
# 2691| r2691_5(glval<int>) = VariableAddress[#return] :
# 2691| v2691_6(void) = ReturnValue : &:r2691_5, m2693_4
# 2691| v2691_7(void) = AliasedUse : m2691_3
# 2691| v2691_8(void) = ExitFunction :
many-defs-per-use.cpp:
# 34| void many_defs_per_use()
# 34| Block 0

View File

@@ -2686,4 +2686,13 @@ void test(bool b)
twice_call_use(b ? "" : "");
}
namespace concepts {
int requires_use() {
int y = requires { sizeof(int) > 0; };
return y;
}
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -17422,6 +17422,23 @@ ir.cpp:
# 2684| v2684_7(void) = AliasedUse : ~m?
# 2684| v2684_8(void) = ExitFunction :
# 2691| int concepts::requires_use()
# 2691| Block 0
# 2691| v2691_1(void) = EnterFunction :
# 2691| mu2691_2(unknown) = AliasedDefinition :
# 2691| mu2691_3(unknown) = InitializeNonLocal :
# 2692| r2692_1(glval<int>) = VariableAddress[y] :
#-----| r0_1(int) = Constant[1] :
#-----| mu0_2(int) = Store[y] : &:r2692_1, r0_1
# 2693| r2693_1(glval<int>) = VariableAddress[#return] :
# 2693| r2693_2(glval<int>) = VariableAddress[y] :
# 2693| r2693_3(int) = Load[y] : &:r2693_2, ~m?
# 2693| mu2693_4(int) = Store[#return] : &:r2693_1, r2693_3
# 2691| r2691_4(glval<int>) = VariableAddress[#return] :
# 2691| v2691_5(void) = ReturnValue : &:r2691_4, ~m?
# 2691| v2691_6(void) = AliasedUse : ~m?
# 2691| v2691_7(void) = ExitFunction :
many-defs-per-use.cpp:
# 34| void many_defs_per_use()
# 34| Block 0

View File

@@ -1,6 +1,6 @@
| containserror.cpp:0:0:0:0 | containserror.cpp | query-tests/Diagnostics/containserror.cpp | fromSource, normalTermination |
| containswarning.cpp:0:0:0:0 | containswarning.cpp | query-tests/Diagnostics/containswarning.cpp | fromSource, normalTermination |
| doesnotcompile.cpp:0:0:0:0 | doesnotcompile.cpp | query-tests/Diagnostics/doesnotcompile.cpp | ExtractionProblem (severity 1), fromSource, normalTermination |
| containserror.cpp:0:0:0:0 | containserror.cpp | containserror.cpp | fromSource, normalTermination |
| containswarning.cpp:0:0:0:0 | containswarning.cpp | containswarning.cpp | fromSource, normalTermination |
| doesnotcompile.cpp:0:0:0:0 | doesnotcompile.cpp | doesnotcompile.cpp | ExtractionProblem (severity 1), fromSource, normalTermination |
| file://:0:0:0:0 | | | |
| header.h:0:0:0:0 | header.h | query-tests/Diagnostics/header.h | fromSource |
| successful.cpp:0:0:0:0 | successful.cpp | query-tests/Diagnostics/successful.cpp | fromSource, normalTermination |
| header.h:0:0:0:0 | header.h | header.h | fromSource |
| successful.cpp:0:0:0:0 | successful.cpp | successful.cpp | fromSource, normalTermination |

View File

@@ -1,16 +1,16 @@
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:9:5:9:10 | call to proto6 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:9:5:9:10 | call to proto6 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:10:5:10:10 | call to proto7 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:10:5:10:10 | call to proto7 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:12:5:12:10 | call to proto9 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:12:5:12:10 | call to proto9 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:13:5:13:11 | call to proto10 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:13:5:13:11 | call to proto10 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:14:5:14:11 | call to proto11 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:14:5:14:11 | call to proto11 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:16:5:16:11 | call to proto13 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:16:5:16:11 | call to proto13 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user1.c:9:5:9:6 | call to f1 | query-tests/Documentation/DocumentApi/user1.c |
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user2.c:7:5:7:6 | call to f1 | query-tests/Documentation/DocumentApi/user2.c |
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user1.c:14:5:14:6 | call to f6 | query-tests/Documentation/DocumentApi/user1.c |
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user2.c:10:5:10:6 | call to f6 | query-tests/Documentation/DocumentApi/user2.c |
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:9:5:9:10 | call to proto6 | comment_prototypes_caller1.c |
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:9:5:9:10 | call to proto6 | comment_prototypes_caller2.c |
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:10:5:10:10 | call to proto7 | comment_prototypes_caller1.c |
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:10:5:10:10 | call to proto7 | comment_prototypes_caller2.c |
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:12:5:12:10 | call to proto9 | comment_prototypes_caller1.c |
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:12:5:12:10 | call to proto9 | comment_prototypes_caller2.c |
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:13:5:13:11 | call to proto10 | comment_prototypes_caller1.c |
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:13:5:13:11 | call to proto10 | comment_prototypes_caller2.c |
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:14:5:14:11 | call to proto11 | comment_prototypes_caller1.c |
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:14:5:14:11 | call to proto11 | comment_prototypes_caller2.c |
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:16:5:16:11 | call to proto13 | comment_prototypes_caller1.c |
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:16:5:16:11 | call to proto13 | comment_prototypes_caller2.c |
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user1.c:9:5:9:6 | call to f1 | user1.c |
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user2.c:7:5:7:6 | call to f1 | user2.c |
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user1.c:14:5:14:6 | call to f6 | user1.c |
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user2.c:10:5:10:6 | call to f6 | user2.c |

View File

@@ -1,4 +1,4 @@
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibC<\|>unknown | 5 |
| /query-tests/Metrics/Dependencies/include.h<\|>LibD<\|>unknown | 1 |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibA<\|>unknown | 1 |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibB<\|>unknown | 1 |
| /main.cpp<\|>LibC<\|>unknown | 5 |
| /include.h<\|>LibD<\|>unknown | 1 |
| /main.cpp<\|>LibA<\|>unknown | 1 |
| /main.cpp<\|>LibB<\|>unknown | 1 |

View File

@@ -1,4 +1,4 @@
| /query-tests/Metrics/Dependencies/include.h<\|>LibD<\|>unknown | include.h:0:0:0:0 | include.h |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibA<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibB<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibC<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
| /include.h<\|>LibD<\|>unknown | include.h:0:0:0:0 | include.h |
| /main.cpp<\|>LibA<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
| /main.cpp<\|>LibB<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
| /main.cpp<\|>LibC<\|>unknown | main.cpp:0:0:0:0 | main.cpp |

View File

@@ -2,29 +2,36 @@ edges
| test1.c:7:26:7:29 | **argv | test1.c:8:11:8:14 | call to atoi | provenance | TaintFunction |
| test1.c:8:11:8:14 | call to atoi | test1.c:9:9:9:9 | i | provenance | |
| test1.c:8:11:8:14 | call to atoi | test1.c:11:9:11:9 | i | provenance | |
| test1.c:8:11:8:14 | call to atoi | test1.c:12:9:12:9 | i | provenance | |
| test1.c:8:11:8:14 | call to atoi | test1.c:13:9:13:9 | i | provenance | |
| test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i | provenance | |
| test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i | provenance | |
| test1.c:13:9:13:9 | i | test1.c:48:16:48:16 | i | provenance | |
| test1.c:16:16:16:16 | i | test1.c:18:16:18:16 | i | provenance | |
| test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i | provenance | |
| test1.c:48:16:48:16 | i | test1.c:51:3:51:7 | ... = ... | provenance | |
| test1.c:51:3:51:7 | ... = ... | test1.c:53:15:53:15 | j | provenance | |
| test1.c:9:9:9:9 | i | test1.c:18:16:18:16 | i | provenance | |
| test1.c:11:9:11:9 | i | test1.c:34:16:34:16 | i | provenance | |
| test1.c:12:9:12:9 | i | test1.c:42:16:42:16 | i | provenance | |
| test1.c:13:9:13:9 | i | test1.c:50:16:50:16 | i | provenance | |
| test1.c:18:16:18:16 | i | test1.c:20:16:20:16 | i | provenance | |
| test1.c:34:16:34:16 | i | test1.c:35:11:35:11 | i | provenance | |
| test1.c:42:16:42:16 | i | test1.c:43:11:43:11 | i | provenance | |
| test1.c:50:16:50:16 | i | test1.c:53:3:53:7 | ... = ... | provenance | |
| test1.c:53:3:53:7 | ... = ... | test1.c:55:15:55:15 | j | provenance | |
nodes
| test1.c:7:26:7:29 | **argv | semmle.label | **argv |
| test1.c:8:11:8:14 | call to atoi | semmle.label | call to atoi |
| test1.c:9:9:9:9 | i | semmle.label | i |
| test1.c:11:9:11:9 | i | semmle.label | i |
| test1.c:12:9:12:9 | i | semmle.label | i |
| test1.c:13:9:13:9 | i | semmle.label | i |
| test1.c:16:16:16:16 | i | semmle.label | i |
| test1.c:18:16:18:16 | i | semmle.label | i |
| test1.c:32:16:32:16 | i | semmle.label | i |
| test1.c:33:11:33:11 | i | semmle.label | i |
| test1.c:48:16:48:16 | i | semmle.label | i |
| test1.c:51:3:51:7 | ... = ... | semmle.label | ... = ... |
| test1.c:53:15:53:15 | j | semmle.label | j |
| test1.c:20:16:20:16 | i | semmle.label | i |
| test1.c:34:16:34:16 | i | semmle.label | i |
| test1.c:35:11:35:11 | i | semmle.label | i |
| test1.c:42:16:42:16 | i | semmle.label | i |
| test1.c:43:11:43:11 | i | semmle.label | i |
| test1.c:50:16:50:16 | i | semmle.label | i |
| test1.c:53:3:53:7 | ... = ... | semmle.label | ... = ... |
| test1.c:55:15:55:15 | j | semmle.label | j |
subpaths
#select
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | **argv | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | **argv | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | **argv | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |
| test1.c:20:16:20:16 | i | test1.c:7:26:7:29 | **argv | test1.c:20:16:20:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |
| test1.c:35:11:35:11 | i | test1.c:7:26:7:29 | **argv | test1.c:35:11:35:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |
| test1.c:43:11:43:11 | i | test1.c:7:26:7:29 | **argv | test1.c:43:11:43:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |
| test1.c:55:15:55:15 | j | test1.c:7:26:7:29 | **argv | test1.c:55:15:55:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | **argv | a command-line argument |

View File

@@ -11,6 +11,8 @@ int main(int argc, char *argv[]) {
test3(i);
test4(i);
test5(i);
test6(i);
test7(argv[1]);
}
void test1(int i) {
@@ -38,7 +40,7 @@ void test3(int i) {
}
void test4(int i) {
myArray[i] = 0; // BAD: i has not been validated [NOT REPORTED]
myArray[i] = 0; // BAD: i has not been validated
if ((i < 0) || (i >= 10)) return;
@@ -52,3 +54,26 @@ void test5(int i) {
j = myArray[j]; // BAD: j has not been validated
}
extern int myTable[256];
void test6(int i) {
unsigned char s = i;
myTable[s] = 0; // GOOD: Input is small [FALSE POSITIVE]
}
typedef void FILE;
#define EOF (-1)
int getc(FILE*);
extern int myMaxCharTable[256];
void test7(FILE* fp) {
int ch;
while ((ch = getc(fp)) != EOF) {
myMaxCharTable[ch] = 0; // GOOD
}
}

View File

@@ -11,14 +11,14 @@ char *strcpy(char *s1, const char *s2);
//// Test code /////
void bad0(char *str) {
static void bad0(char *str) {
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(strlen(str));
strcpy(buffer, str);
free(buffer);
}
void good0(char *str) {
static void good0(char *str) {
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc(strlen(str)+1);
strcpy(buffer, str);
@@ -26,7 +26,7 @@ void good0(char *str) {
}
void bad1(char *str) {
static void bad1(char *str) {
int len = strlen(str);
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(len);
@@ -34,7 +34,7 @@ void bad1(char *str) {
free(buffer);
}
void good1(char *str) {
static void good1(char *str) {
int len = strlen(str);
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc(len+1);
@@ -43,7 +43,7 @@ void good1(char *str) {
}
void bad2(char *str) {
static void bad2(char *str) {
int len = strlen(str);
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(len);
@@ -51,7 +51,7 @@ void bad2(char *str) {
free(buffer);
}
void good2(char *str) {
static void good2(char *str) {
int len = strlen(str)+1;
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc(len);
@@ -59,14 +59,14 @@ void good2(char *str) {
free(buffer);
}
void bad3(char *str) {
static void bad3(char *str) {
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(strlen(str) * sizeof(char));
strcpy(buffer, str);
free(buffer);
}
void good3(char *str) {
static void good3(char *str) {
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc((strlen(str) + 1) * sizeof(char));
strcpy(buffer, str);
@@ -75,7 +75,7 @@ void good3(char *str) {
void *memcpy(void *s1, const void *s2, size_t n);
void good4(char *str) {
static void good4(char *str) {
// GOOD -- allocating a non zero-terminated string
int len = strlen(str);
char *buffer = malloc(len);

View File

@@ -19,28 +19,28 @@ int strcmp(const char *s1, const char *s2);
//// Test code /////
void bad1(wchar_t *wstr) {
static void bad1(wchar_t *wstr) {
// BAD -- Not allocating space for '\0' terminator
wchar_t *wbuffer = (wchar_t *)malloc(wcslen(wstr));
wcscpy(wbuffer, wstr);
free(wbuffer);
}
void bad2(wchar_t *wstr) {
static void bad2(wchar_t *wstr) {
// BAD -- Not allocating space for '\0' terminator
wchar_t *wbuffer = (wchar_t *)malloc(wcslen(wstr) * sizeof(wchar_t));
wcscpy(wbuffer, wstr);
free(wbuffer);
}
void good1(wchar_t *wstr) {
static void good1(wchar_t *wstr) {
// GOOD -- Allocating extra character for terminator
wchar_t *wbuffer = (wchar_t *)malloc((wcslen(wstr) + 1) * sizeof(wchar_t));
wcscpy(wbuffer, wstr);
free(wbuffer);
}
void bad3(char *str) {
static void bad3(char *str) {
// BAD -- zero-termination proved by sprintf (as destination)
char *buffer = (char *)malloc(strlen(str));
sprintf(buffer, "%s", str);
@@ -50,7 +50,7 @@ void bad3(char *str) {
void decode(char *dest, char *src);
void wdecode(wchar_t *dest, wchar_t *src);
void bad4(char *str) {
static void bad4(char *str) {
// BAD -- zero-termination proved by wprintf (as parameter)
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
@@ -58,7 +58,7 @@ void bad4(char *str) {
free(buffer);
}
void bad5(char *str) {
static void bad5(char *str) {
// BAD -- zero-termination proved by strcat (as destination)
char *buffer = (char *)malloc(strlen(str));
buffer[0] = 0;
@@ -66,7 +66,7 @@ void bad5(char *str) {
free(buffer);
}
void bad6(char *str, char *dest) {
static void bad6(char *str, char *dest) {
// BAD -- zero-termination proved by strcat (as source)
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
@@ -74,7 +74,7 @@ void bad6(char *str, char *dest) {
free(buffer);
}
void bad7(char *str, char *str2) {
static void bad7(char *str, char *str2) {
// BAD -- zero-termination proved by strcmp
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
@@ -84,7 +84,7 @@ void bad7(char *str, char *str2) {
free(buffer);
}
void bad8(wchar_t *str) {
static void bad8(wchar_t *str) {
// BAD -- zero-termination proved by wcslen
wchar_t *wbuffer = (wchar_t *)malloc(wcslen(str));
wdecode(wbuffer, str);
@@ -94,21 +94,21 @@ void bad8(wchar_t *str) {
free(wbuffer);
}
void good2(char *str, char *dest) {
static void good2(char *str, char *dest) {
// GOOD -- zero-termination not proven
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
free(buffer);
}
void bad9(wchar_t *wstr) {
static void bad9(wchar_t *wstr) {
// BAD -- using new
wchar_t *wbuffer = new wchar_t[wcslen(wstr)];
wcscpy(wbuffer, wstr);
delete wbuffer;
}
void good3(char *str) {
static void good3(char *str) {
// GOOD -- zero-termination not required for this printf
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
@@ -116,7 +116,7 @@ void good3(char *str) {
free(buffer);
}
void good4(char *str) {
static void good4(char *str) {
// GOOD -- zero-termination not required for this printf
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);

View File

@@ -38,35 +38,35 @@ namespace std
//// Test code /////
void bad1(char *str) {
static void bad1(char *str) {
// BAD -- Not allocating space for '\0' terminator [NOT DETECTED]
char *buffer = (char *)malloc(strlen(str));
std::string str2(buffer);
free(buffer);
}
void good1(char *str) {
static void good1(char *str) {
// GOOD --- copy does not overrun due to size limit
char *buffer = (char *)malloc(strlen(str));
std::string str2(buffer, strlen(str));
free(buffer);
}
void bad2(wchar_t *str) {
static void bad2(wchar_t *str) {
// BAD -- Not allocating space for '\0' terminator [NOT DETECTED]
wchar_t *buffer = (wchar_t *)calloc(wcslen(str), sizeof(wchar_t));
wcscpy(buffer, str);
free(buffer);
}
void bad3(wchar_t *str) {
static void bad3(wchar_t *str) {
// BAD -- Not allocating space for '\0' terminator
wchar_t *buffer = (wchar_t *)calloc(sizeof(wchar_t), wcslen(str));
wcscpy(buffer, str);
free(buffer);
}
void bad4(char *str) {
static void bad4(char *str) {
// BAD -- Not allocating space for '\0' terminator
char *buffer = (char *)realloc(0, strlen(str));
strcpy(buffer, str);

View File

@@ -1,4 +1,6 @@
edges
| main.cpp:7:27:7:30 | **argv | main.cpp:8:17:8:20 | **argv | provenance | |
| main.cpp:8:17:8:20 | **argv | test.c:10:28:10:31 | **argv | provenance | |
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v | provenance | |
| test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:13:27:13 | v | provenance | |
| test2.cpp:27:13:27:13 | v | test2.cpp:12:21:12:21 | v | provenance | |
@@ -6,18 +8,15 @@ edges
| test2.cpp:38:13:38:16 | call to atoi | test2.cpp:39:3:39:18 | ... = ... | provenance | |
| test2.cpp:38:13:38:16 | call to atoi | test2.cpp:39:9:39:11 | num | provenance | |
| test2.cpp:39:3:39:18 | ... = ... | test2.cpp:40:3:40:5 | num | provenance | |
| test3.c:10:27:10:30 | **argv | test.c:11:24:11:27 | call to atoi | provenance | TaintFunction |
| test3.c:10:27:10:30 | **argv | test.c:41:5:41:24 | ... = ... | provenance | TaintFunction |
| test3.c:10:27:10:30 | **argv | test.c:51:5:51:24 | ... = ... | provenance | TaintFunction |
| test5.cpp:5:5:5:17 | *getTaintedInt | test5.cpp:17:6:17:18 | call to getTaintedInt | provenance | |
| test5.cpp:5:5:5:17 | *getTaintedInt | test5.cpp:18:6:18:18 | call to getTaintedInt | provenance | |
| test5.cpp:9:7:9:9 | gets output argument | test5.cpp:10:9:10:27 | call to strtoul | provenance | TaintFunction |
| test5.cpp:10:9:10:27 | call to strtoul | test5.cpp:5:5:5:17 | *getTaintedInt | provenance | |
| test5.cpp:18:2:18:20 | ... = ... | test5.cpp:19:6:19:6 | y | provenance | |
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:18:2:18:20 | ... = ... | provenance | |
| test.c:10:27:10:30 | **argv | test.c:11:24:11:27 | call to atoi | provenance | TaintFunction |
| test.c:10:27:10:30 | **argv | test.c:41:5:41:24 | ... = ... | provenance | TaintFunction |
| test.c:10:27:10:30 | **argv | test.c:51:5:51:24 | ... = ... | provenance | TaintFunction |
| test.c:10:28:10:31 | **argv | test.c:11:24:11:27 | call to atoi | provenance | TaintFunction |
| test.c:10:28:10:31 | **argv | test.c:41:5:41:24 | ... = ... | provenance | TaintFunction |
| test.c:10:28:10:31 | **argv | test.c:51:5:51:24 | ... = ... | provenance | TaintFunction |
| test.c:11:24:11:27 | call to atoi | test.c:14:15:14:28 | maxConnections | provenance | |
| test.c:41:5:41:24 | ... = ... | test.c:44:7:44:10 | len2 | provenance | |
| test.c:41:5:41:24 | ... = ... | test.c:44:7:44:12 | ... -- | provenance | |
@@ -26,6 +25,8 @@ edges
| test.c:51:5:51:24 | ... = ... | test.c:54:7:54:12 | ... -- | provenance | |
| test.c:54:7:54:12 | ... -- | test.c:54:7:54:10 | len3 | provenance | |
nodes
| main.cpp:7:27:7:30 | **argv | semmle.label | **argv |
| main.cpp:8:17:8:20 | **argv | semmle.label | **argv |
| test2.cpp:12:21:12:21 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument |
@@ -35,7 +36,6 @@ nodes
| test2.cpp:39:3:39:18 | ... = ... | semmle.label | ... = ... |
| test2.cpp:39:9:39:11 | num | semmle.label | num |
| test2.cpp:40:3:40:5 | num | semmle.label | num |
| test3.c:10:27:10:30 | **argv | semmle.label | **argv |
| test5.cpp:5:5:5:17 | *getTaintedInt | semmle.label | *getTaintedInt |
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument |
| test5.cpp:10:9:10:27 | call to strtoul | semmle.label | call to strtoul |
@@ -43,7 +43,7 @@ nodes
| test5.cpp:18:2:18:20 | ... = ... | semmle.label | ... = ... |
| test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test.c:10:27:10:30 | **argv | semmle.label | **argv |
| test.c:10:28:10:31 | **argv | semmle.label | **argv |
| test.c:11:24:11:27 | call to atoi | semmle.label | call to atoi |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:41:5:41:24 | ... = ... | semmle.label | ... = ... |
@@ -61,19 +61,7 @@ subpaths
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | **argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | **argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | **argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | **argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | **argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | **argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | **argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | **argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | main.cpp:7:27:7:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test.c:14:15:14:28 | maxConnections | main.cpp:7:27:7:30 | **argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test.c:44:7:44:10 | len2 | main.cpp:7:27:7:30 | **argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test.c:54:7:54:10 | len3 | main.cpp:7:27:7:30 | **argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | main.cpp:7:27:7:30 | **argv | a command-line argument |

View File

@@ -4,20 +4,15 @@
| test2.cpp:17:11:17:22 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:39:9:39:18 | ... + ... | $@ flows an expression which might overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test2.cpp:40:3:40:13 | ... += ... | $@ flows an expression which might overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test3.c:12:11:12:34 | * ... | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test3.c:12:11:12:34 | * ... | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | **argv | a command-line argument |
| test3.c:13:11:13:20 | * ... | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test3.c:13:11:13:20 | * ... | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | **argv | a command-line argument |
| test4.cpp:13:7:13:20 | access to array | $@ flows an expression which might overflow negatively. | test4.cpp:8:27:8:30 | **argv | a command-line argument |
| test3.c:12:11:12:34 | * ... | $@ flows an expression which might overflow negatively. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test3.c:13:11:13:20 | * ... | $@ flows an expression which might overflow negatively. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test4.cpp:13:7:13:20 | access to array | $@ flows an expression which might overflow negatively. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test5.cpp:10:9:10:27 | call to strtoul | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:17:6:17:27 | ... * ... | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:13 | ... * ... | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test6.cpp:11:10:11:15 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | fscanf output argument | value read by fscanf |
| test6.cpp:16:10:16:15 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | fscanf output argument | value read by fscanf |
| test6.cpp:30:11:30:16 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | fscanf output argument | value read by fscanf |
| test.c:14:15:14:35 | ... * ... | $@ flows an expression which might overflow. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:35 | ... * ... | $@ flows an expression which might overflow. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:44:7:44:12 | ... -- | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:44:7:44:12 | ... -- | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | **argv | a command-line argument |
| test.c:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | **argv | a command-line argument |
| test.c:14:15:14:35 | ... * ... | $@ flows an expression which might overflow. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test.c:44:7:44:12 | ... -- | $@ flows an expression which might overflow negatively. | main.cpp:7:27:7:30 | **argv | a command-line argument |
| test.c:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | main.cpp:7:27:7:30 | **argv | a command-line argument |

View File

@@ -0,0 +1,12 @@
extern "C" {
int main1(int argc, char** argv);
int main3(int argc, char** argv);
}
int main4(int argc, char** argv);
int main(int argc, char** argv) {
main1(argc, argv);
main3(argc, argv);
main4(argc, argv);
return 0;
}

View File

@@ -7,7 +7,7 @@ void startServer(int heapSize);
typedef unsigned long size_t;
size_t strlen(const char *s);
int main(int argc, char** argv) {
int main1(int argc, char** argv) {
int maxConnections = atoi(argv[1]);
// BAD: arithmetic on a user input without any validation

View File

@@ -7,7 +7,7 @@
// Regression test for ODASA-6054: IntegerOverflowTainted should
// not report a result if the overflow happens in a macro expansion
// from a macro that is defined in a system header.
int main(int argc, char **argv) {
int main3(int argc, char **argv) {
char *cmd = argv[0];
int x = (int)(unsigned char)*cmd; // BAD: overflow
int y = CAST(*cmd); // BAD: overflow in macro expansion (macro is not from a system header)

View File

@@ -5,7 +5,7 @@
// by comparing the value to 0. This means that the cast cannot overflow,
// regardless of what the input type is.
int main(int argc, char **argv) {
int main4(int argc, char **argv) {
char *p = argv[0];
if (!p[0]) { // GOOD: cast to bool.
return 1;

View File

@@ -50,7 +50,7 @@ int val();
const char *global1 = mysql_get_client_info();
const char *global2 = "abc";
void test1()
void test7()
{
int sock = socket(val(), val(), val());

View File

@@ -1,3 +1,7 @@
## 1.7.27
No user-facing changes.
## 1.7.26
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.26
lastReleaseVersion: 1.7.27

View File

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

View File

@@ -1,3 +1,7 @@
## 1.7.27
No user-facing changes.
## 1.7.26
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.26
lastReleaseVersion: 1.7.27

View File

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

View File

@@ -1,3 +1,7 @@
## 3.0.1
No user-facing changes.
## 3.0.0
### Breaking Changes

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 3.0.0
lastReleaseVersion: 3.0.1

View File

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

View File

@@ -53,7 +53,6 @@ private predicate idOf(AstNode x, int y) = equivalenceRelation(id/2)(x, y)
private module CfgInput implements CfgShared::InputSig<Location> {
private import ControlFlowGraphImpl as Impl
private import Completion as Comp
private import Splitting as Splitting
private import SuccessorType as ST
private import semmle.code.csharp.Caching
@@ -80,10 +79,6 @@ private module CfgInput implements CfgShared::InputSig<Location> {
Impl::scopeLast(scope, last, c)
}
class SplitKindBase = Splitting::TSplitKind;
class Split = Splitting::Split;
class SuccessorType = ST::SuccessorType;
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
@@ -102,7 +97,21 @@ private module CfgInput implements CfgShared::InputSig<Location> {
}
}
import CfgShared::Make<Location, CfgInput>
private module CfgSplittingInput implements CfgShared::SplittingInputSig<Location, CfgInput> {
private import Splitting as S
class SplitKindBase = S::TSplitKind;
class Split = S::Split;
}
private module ConditionalCompletionSplittingInput implements
CfgShared::ConditionalCompletionSplittingInputSig<Location, CfgInput, CfgSplittingInput>
{
import Splitting::ConditionalCompletionSplitting::ConditionalCompletionSplittingInput
}
import CfgShared::MakeWithSplitting<Location, CfgInput, CfgSplittingInput, ConditionalCompletionSplittingInput>
/**
* A compilation.

View File

@@ -5,7 +5,8 @@
*/
import csharp
private import Completion
private import Completion as Comp
private import Comp
private import ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg
private import semmle.code.csharp.controlflow.internal.PreSsa
@@ -260,10 +261,12 @@ module ConditionalCompletionSplitting {
ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }
ConditionalCompletion getCompletion() { result = completion }
override string toString() { result = completion.toString() }
}
private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
private class ConditionalCompletionSplitKind_ extends SplitKind, TConditionalCompletionSplitKind {
override int getListOrder() { result = InitializerSplitting::getNextListOrder() }
override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) }
@@ -271,89 +274,64 @@ module ConditionalCompletionSplitting {
override string toString() { result = "ConditionalCompletion" }
}
int getNextListOrder() { result = InitializerSplitting::getNextListOrder() + 1 }
module ConditionalCompletionSplittingInput {
private import Completion as Comp
private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
{
ConditionalCompletion completion;
class ConditionalCompletion = Comp::ConditionalCompletion;
ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
class ConditionalCompletionSplitKind extends ConditionalCompletionSplitKind_, TSplitKind { }
override ConditionalCompletionSplitKind getKind() { any() }
class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, completion) and
bindingset[parent, parentCompletion]
predicate condPropagateExpr(
AstNode parent, ConditionalCompletion parentCompletion, AstNode child,
ConditionalCompletion childCompletion
) {
child = parent.(LogicalNotExpr).getOperand() and
childCompletion.getDual() = parentCompletion
or
childCompletion = parentCompletion and
(
last(succ.(LogicalNotExpr).getOperand(), pred, c) and
completion.(BooleanCompletion).getDual() = c
child = parent.(LogicalAndExpr).getAnOperand()
or
last(succ.(LogicalAndExpr).getAnOperand(), pred, c) and
completion = c
child = parent.(LogicalOrExpr).getAnOperand()
or
last(succ.(LogicalOrExpr).getAnOperand(), pred, c) and
completion = c
parent = any(ConditionalExpr ce | child = [ce.getThen(), ce.getElse()])
or
succ =
any(ConditionalExpr ce |
last([ce.getThen(), ce.getElse()], pred, c) and
completion = c
)
child = parent.(SwitchExpr).getACase()
or
succ =
child = parent.(SwitchCaseExpr).getBody()
or
parent =
any(NullCoalescingExpr nce |
exists(Expr operand |
last(operand, pred, c) and
completion = c
|
if c instanceof NullnessCompletion
then operand = nce.getRightOperand()
else operand = nce.getAnOperand()
)
if childCompletion instanceof NullnessCompletion
then child = nce.getRightOperand()
else child = nce.getAnOperand()
)
)
or
child = parent.(NotPatternExpr).getPattern() and
childCompletion.getDual() = parentCompletion
or
child = parent.(IsExpr).getPattern() and
parentCompletion.(BooleanCompletion).getValue() =
childCompletion.(MatchingCompletion).getValue()
or
childCompletion = parentCompletion and
(
child = parent.(AndPatternExpr).getAnOperand()
or
last(succ.(SwitchExpr).getACase(), pred, c) and
completion = c
child = parent.(OrPatternExpr).getAnOperand()
or
last(succ.(SwitchCaseExpr).getBody(), pred, c) and
completion = c
child = parent.(RecursivePatternExpr).getAChildExpr()
or
last(succ.(NotPatternExpr).getPattern(), pred, c) and
completion.(MatchingCompletion).getDual() = c
or
last(succ.(IsExpr).getPattern(), pred, c) and
completion.(BooleanCompletion).getValue() = c.(MatchingCompletion).getValue()
or
last(succ.(AndPatternExpr).getAnOperand(), pred, c) and
completion = c
or
last(succ.(OrPatternExpr).getAnOperand(), pred, c) and
completion = c
or
last(succ.(RecursivePatternExpr).getAChildExpr(), pred, c) and
completion = c
or
last(succ.(PropertyPatternExpr).getPattern(_), pred, c) and
completion = c
child = parent.(PropertyPatternExpr).getPattern(_)
)
}
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
this.appliesTo(last) and
scopeLast(scope, last, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) { none() }
}
int getNextListOrder() { result = InitializerSplitting::getNextListOrder() + 1 }
}
module AssertionSplitting {

View File

@@ -42,7 +42,7 @@ private module LogForgingConfig implements DataFlow::ConfigSig {
*/
module LogForging = TaintTracking::Global<LogForgingConfig>;
/** A source of remote user input. */
/** A source supported by the current threat model. */
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
private class HtmlSanitizer extends Sanitizer {

View File

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

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.0.9
lastReleaseVersion: 1.0.10

View File

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

View File

@@ -639,7 +639,7 @@ public class Inheritance
public override string Prop { get { return tainted; } }
}
public abstract class BaseContent
public abstract class BaseContent
{
public abstract object GetValue();
@@ -961,3 +961,30 @@ public class Fanout
return other + b2.GetValue();
}
}
public class AvoidDuplicateLifted
{
public class A
{
public object Prop { get; set; }
// contentbased-summary=Models;AvoidDuplicateLifted+A;true;GetValue;();;Argument[this].Property[Models.AvoidDuplicateLifted+A.Prop];ReturnValue;value;dfc-generated
// summary=Models;AvoidDuplicateLifted+A;true;GetValue;();;Argument[this];ReturnValue;taint;df-generated
public virtual object GetValue()
{
return Prop;
}
}
public class B : A
{
private object field;
// No content based summary as field is a dead synthetic field.
// summary=Models;AvoidDuplicateLifted+A;true;GetValue;();;Argument[this];ReturnValue;taint;df-generated
public override object GetValue()
{
return field;
}
}
}

View File

@@ -27,8 +27,8 @@ This example of an extensible predicate for a source is taken from the core Java
.. code-block:: ql
extensible predicate sourceModel(
string package, string type, boolean subtypes, string name,
string signature, string ext, string output, string kind,
string package, string type, boolean subtypes, string name,
string signature, string ext, string output, string kind,
string provenance
);
@@ -36,7 +36,7 @@ An extensible predicate is a CodeQL predicate with the following restrictions:
- It uses the ``extensible`` keyword.
- It has no body.
- All predicate parameters have primitive types.
- All predicate parameters have type ``string``, ``int``, ``float``, ``boolean``, or ``date``.
- It is not in a module.
Columns shared by all extensible predicates

View File

@@ -0,0 +1,137 @@
.. _codeql-cli-2.19.1:
==========================
CodeQL 2.19.1 (2024-10-04)
==========================
.. contents:: Contents
:depth: 2
:local:
:backlinks: none
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
Security Coverage
-----------------
CodeQL 2.19.1 runs a total of 426 security queries when configured with the Default suite (covering 164 CWE). The Extended suite enables an additional 128 queries (covering 34 more CWE).
CodeQL CLI
----------
New Features
~~~~~~~~~~~~
* The command :code:`codeql generate query-help` now supports Markdown help files.
The Markdown help format is commonly used in custom CodeQL query packs. This new feature allows us to generate SARIF reporting descriptors for CodeQL queries that include Markdown help directly from a query Markdown help file.
* Added a new command, :code:`codeql resolve packs`. This command shows each step in the pack search process, including what packs were found in each step. With the
:code:`--show-hidden-packs` option, it can also show details on which packs were hidden by packs found earlier in the search sequence. :code:`codeql resolve packs` is intended as a replacement for most uses of :code:`codeql resolve qlpacks`, whose output is both less detailed and less accurate.
Query Packs
-----------
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
C/C++
"""""
* Fixed false positives in the :code:`cpp/wrong-number-format-arguments` ("Too few arguments to formatting function") query when the formatting function has been declared implicitly.
C#
""
* C#: The indexer and :code:`Add` method on :code:`System.Web.UI.AttributeCollection` is no longer considered an HTML sink.
Java/Kotlin
"""""""""""
* Added taint summary model for :code:`org.springframework.core.io.InputStreamSource#getInputStream()`.
New Queries
~~~~~~~~~~~
Python
""""""
* The :code:`py/cors-misconfiguration-with-credentials` query, which finds insecure CORS middleware configurations.
Query Metadata Changes
~~~~~~~~~~~~~~~~~~~~~~
Golang
""""""
* The precision of the :code:`go/incorrect-integer-conversion-query` query was decreased from :code:`very-high` to :code:`high`, since there is at least one known class of false positives involving dynamic bounds checking.
Language Libraries
------------------
Breaking Changes
~~~~~~~~~~~~~~~~
C#
""
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using :code:`Attribute.Getter` or :code:`Attribute.Setter` in the model :code:`ext` field applies the model to the getter or setter for properties and indexers. Prior to this change :code:`Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the :code:`Attribute` feature directly on a property for a property setter needs to be changed to :code:`Attribute.Setter`.
* C#: Remove all CIL tables and related QL library functionality.
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
C#
""
* :code:`DataFlow::Node` instances are no longer created for library methods and fields that are not callable (either statically or dynamically) or otherwise referred to from source code. This may affect third-party queries that use these nodes to identify library methods or fields that are present in DLL files where those methods or fields are unreferenced. If this presents a problem, consider using :code:`Callable` and other non-dataflow classes to identify such library entities.
* C#: Add extractor support for attributes on indexers.
Golang
""""""
* A method in the method set of an embedded field of a struct should not be promoted to the method set of the struct if the struct has a method with the same name. This was not being enforced, which meant that there were two methods with the same qualified name, and models were sometimes being applied when they shouldn't have been. This has now been fixed.
Python
""""""
* The common sanitizer guard :code:`StringConstCompareBarrier` has been renamed to :code:`ConstCompareBarrier` and expanded to cover comparisons with other constant values such as :code:`None`. This may result in fewer false positive results for several queries.
Swift
"""""
* All AST classes in :code:`codeql.swift.elements` are now :code:`final`, which means that it is no longer possible to :code:`override` predicates defined in those classes (it is, however, still possible to :code:`extend` the classes).
Deprecated APIs
~~~~~~~~~~~~~~~
C#
""
* The class :code:`ThreatModelFlowSource` has been renamed to :code:`ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. :code:`ThreatModelFlowSource` has been marked as deprecated.
Golang
""""""
* The class :code:`ThreatModelFlowSource` has been renamed to :code:`ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. :code:`ThreatModelFlowSource` has been marked as deprecated.
Java/Kotlin
"""""""""""
* The :code:`Field.getSourceDeclaration()` predicate has been deprecated. The result was always the original field, so calls to it can simply be removed.
* The :code:`Field.isSourceDeclaration()` predicate has been deprecated. It always holds.
* The :code:`RefType.nestedName()` predicate has been deprecated, and :code:`RefType.getNestedName()` added to replace it.
* The class :code:`ThreatModelFlowSource` has been renamed to :code:`ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. :code:`ThreatModelFlowSource` has been marked as deprecated.
New Features
~~~~~~~~~~~~
Java/Kotlin
"""""""""""
* The Java extractor and QL libraries now support Java 23.
* Kotlin versions up to 2.1.0\ *x* are now supported.
Python
""""""
* Added support for custom threat-models, which can be used in most of our taint-tracking queries, see our `documentation <https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#extending-codeql-coverage-with-threat-models>`__ for more details.

View File

@@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here <https://docs.g
.. toctree::
:maxdepth: 1
codeql-cli-2.19.1
codeql-cli-2.19.0
codeql-cli-2.18.4
codeql-cli-2.18.3

View File

@@ -101,7 +101,7 @@
latest version of CodeQL...</div>
</div>
<div class="Subhead border-0">
<a href="codeql-overview/supported-languages-and-frameworks/">
<a href="../codeql-query-help/codeql-cwe-coverage/">
<div class="Subhead-heading f4 text-center">CodeQL coverage of CWEs</div>
</a>
<div class="Subhead-description">Detailed information on the coverage of Common Weakness Enumerations (CWEs) in the latest release...</div>

View File

@@ -4,10 +4,10 @@
Modules
#######
Modules provide a way of organizing QL code by grouping together related types, predicates, and other modules.
You can import modules into other files, which avoids duplication, and helps
Modules provide a way of organizing QL code by grouping together related types, predicates, and other modules.
You can import modules into other files, which avoids duplication, and helps
structure your code into more manageable pieces.
.. _defining-module:
@@ -16,7 +16,7 @@ Defining a module
*****************
There are various ways to define modules—here is an example of the simplest way, declaring an
:ref:`explicit module <explicit-modules>` named ``Example`` containing
:ref:`explicit module <explicit-modules>` named ``Example`` containing
a class ``OneTwoThree``:
.. code-block:: ql
@@ -27,17 +27,17 @@ a class ``OneTwoThree``:
this = 1 or this = 2 or this = 3
}
}
}
}
The name of a module can be any `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
that starts with an uppercase or lowercase letter.
that starts with an uppercase or lowercase letter.
``.ql`` or ``.qll`` files also implicitly define modules.
For more information, see ":ref:`kinds-of-modules`."
You can also annotate a module. For more information, see of ":ref:`annotations-overview`."
Note that you can only annotate :ref:`explicit modules <explicit-modules>`.
Note that you can only annotate :ref:`explicit modules <explicit-modules>`.
File modules cannot be annotated.
.. _kinds-of-modules:
@@ -48,7 +48,7 @@ Kinds of modules
File modules
============
Each query file (extension ``.ql``) and library file (extension ``.qll``) implicitly defines
Each query file (extension ``.ql``) and library file (extension ``.qll``) implicitly defines
a module. The module has the same name as the file, but any spaces in the file name are replaced
by underscores (``_``). The contents of the file form the :ref:`body of the module <module-bodies>`.
@@ -57,7 +57,7 @@ by underscores (``_``). The contents of the file form the :ref:`body of the modu
Library modules
---------------
A library module is defined by a ``.qll`` file. It can contain any of the
A library module is defined by a ``.qll`` file. It can contain any of the
elements listed in :ref:`module-bodies` below, apart from select clauses.
For example, consider the following QL library:
@@ -75,19 +75,19 @@ For example, consider the following QL library:
This file defines a library module named ``OneTwoThreeLib``. The body of this module
defines the class ``OneTwoThree``.
.. _query-modules:
.. _query-modules:
Query modules
-------------
A query module is defined by a ``.ql`` file. It can contain any of the elements listed
in :ref:`module-bodies` below.
A query module is defined by a ``.ql`` file. It can contain any of the elements listed
in :ref:`module-bodies` below.
Query modules are slightly different from other modules:
- A query module can't be imported.
- A query module must have at least one query in its
:ref:`namespace <namespaces>`. This is usually a :ref:`select clause <select-clauses>`,
- A query module must have at least one query in its
:ref:`namespace <namespaces>`. This is usually a :ref:`select clause <select-clauses>`,
but can also be a :ref:`query predicate <query-predicates>`.
For example:
@@ -97,7 +97,7 @@ For example:
.. code-block:: ql
import OneTwoThreeLib
from OneTwoThree ott
where ott = 1 or ott = 2
select ott
@@ -110,13 +110,13 @@ This file defines a query module named ``OneTwoQuery``. The body of this module
Explicit modules
================
You can also define a module within another module. This is an explicit module definition.
You can also define a module within another module. This is an explicit module definition.
An explicit module is defined with the keyword ``module`` followed by
the module name, and then the module body enclosed in braces. It can contain any
of the elements listed in ":ref:`module-bodies`" below, apart from select clauses.
An explicit module is defined with the keyword ``module`` followed by
the module name, and then the module body enclosed in braces. It can contain any
of the elements listed in ":ref:`module-bodies`" below, apart from select clauses.
For example, you could add the following QL snippet to the library file **OneTwoThreeLib.qll**
For example, you could add the following QL snippet to the library file **OneTwoThreeLib.qll**
defined :ref:`above <library-modules>`:
.. code-block:: ql
@@ -129,7 +129,7 @@ defined :ref:`above <library-modules>`:
}
}
}
This defines an explicit module named ``M``. The body of this module defines
the class ``OneTwo``.
@@ -226,7 +226,7 @@ Module bodies
*************
The body of a module is the code inside the module definition, for example
the class ``OneTwo`` in the :ref:`explicit module <explicit-modules>` ``M``.
the class ``OneTwo`` in the :ref:`explicit module <explicit-modules>` ``M``.
In general, the body of a module can contain the following constructs:
@@ -243,11 +243,11 @@ In general, the body of a module can contain the following constructs:
Importing modules
*****************
The main benefit of storing code in a module is that you can reuse it in other modules.
To access the contents of an external module, you can import the module using an
The main benefit of storing code in a module is that you can reuse it in other modules.
To access the contents of an external module, you can import the module using an
:ref:`import statement <import-statements>`.
When you import a module this brings all the names in its namespace, apart from :ref:`private` names,
When you import a module this brings all the names in its namespace, apart from :ref:`private` names,
into the :ref:`namespace <namespaces>` of the current module.
.. _import-statements:
@@ -263,7 +263,7 @@ Import statements are used for importing modules. They are of the form:
import <module_expression2>
Import statements are usually listed at the beginning of the module. Each
import statement imports one module. You can import multiple modules by
import statement imports one module. You can import multiple modules by
including multiple import statements (one for each module you want to import).
An import statement can also be :ref:`annotated <annotations-overview>` with
@@ -272,14 +272,14 @@ An import statement can also be :ref:`annotated <annotations-overview>` with
only reachable through deprecated imports in a given context then usage of the
name in that context will generate deprecation warnings.
You can import a module under a different name using the ``as`` keyword,
You can import a module under a different name using the ``as`` keyword,
for example ``import javascript as js``.
The ``<module_expression>`` itself can be a module name, a selection, or a qualified
reference. For more information, see ":ref:`name-resolution`."
For information about how import statements are looked up, see "`Module resolution <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#module-resolution>`__"
in the QL language specification.
in the QL language specification.
Built-in modules
****************
@@ -353,7 +353,7 @@ Sets
The built-in ``InternSets`` module is parameterized by ``Key`` and ``Value`` types
and a ``Value getAValue(Key key)`` relation. The module groups the ``Value``
column by ``Key`` and creates a set for each group of values related by a key.
column by ``Key`` and creates a set for each group of values related by a key.
The ``InternSets`` module exports a functional ``Set getSet(Key key)`` relation
that relates keys with the set of value related to the given key by
@@ -424,3 +424,30 @@ The above query therefore evalutes to:
+----+----+
| 4 | 4 |
+----+----+
.. index:: BigInt
.. _bigint:
BigInt
======
The built-in ``QlBuiltins`` module provides an **experimental** type ``BigInt`` of arbitrary-precision integers.
This type is not available in the CodeQL CLI by default, but you can enable it by passing the ``--allow-experimental=bigint``
option to the CodeQL CLI. Consequently, BigInts are currently disallowed in query results and dbscheme columns.
Unlike ``int`` and ``float``, there is no automatic conversion between ``BigInt`` and other numeric types.
Instead, big integers can be constructed using the ``.toBigInt()`` methods of ``int`` and ``string``.
The other built-in operations are:
* comparisons between ``BigInt``\s: ``=``, ``!=``, ``<``, ``<=``, ``>``, ``>=``,
* conversions from ``BigInt``\s to strings or integers (if within range): ``.toString()``, ``.toInt()``,
* ``BigInt`` arithmetic: binary ``+``, ``-``, ``*``, ``/``, ``%``, unary ``-``,
* bitwise operations: ``.bitAnd(BigInt)``, ``.bitOr(BigInt)``,
``.bitXor(BigInt)``, ``.bitShiftLeft(int)``, ``.bitShiftRightSigned(int)``,
``.bitNot()``,
* aggregates: ``min``, ``max``, (``strict``)\ ``sum``, (``strict``)\ ``count``, ``avg``,
``rank``, ``unique``, ``any``.
* other: ``.pow(int)``, ``.abs()``, ``.gcd(BigInt)``, ``.minimum(BigInt)``,
``.maximum(BigInt)``.

View File

@@ -359,7 +359,7 @@ Kinds of types
Types in QL are either *primitive* types, *database* types, *class* types, *character* types, *class domain* types, type *parameters*, or *instantiation-nested* types.
The primitive types are ``boolean``, ``date``, ``float``, ``int``, and ``string``.
The primitive types are ``boolean``, ``date``, ``float``, ``int``, ``string``, and ``QlBuiltins::BigInt``.
Database types are supplied as part of the database. Each database type has a *name*, which is an identifier starting with an at sign (``@``, U+0040) followed by lower-case letter. Database types have some number of *base types*, which are other database types. In a valid database, the base types relation is non-cyclic.
@@ -433,7 +433,7 @@ Values are the fundamental data that QL programs compute over. This section spec
Kinds of values
~~~~~~~~~~~~~~~
There are six kinds of values in QL: one kind for each of the five primitive types, and *entities*. Each value has a type.
There are seven kinds of values in QL: one kind for each of the six primitive types, and *entities*. Each value has a type.
A boolean value is of type ``boolean``, and may have one of two distinct values: ``true`` or ``false``.
@@ -445,6 +445,8 @@ An integer value is of type ``int``. Each value is a 32-bit two's complement int
A string is a finite sequence of 16-bit characters. The characters are interpreted as Unicode code points.
A :ref:`big integer <bigint>` value is of type ``QlBuiltins::BigInt``. Each value is a signed arbitrary-precision integer.
The database includes a number of opaque entity values. Each such value has a type that is one of the database types, and an identifying integer. An entity value is written as the name of its database type followed by its identifying integer in parentheses. For example, ``@tree(12)``, ``@person(16)``, and ``@location(38132)`` are entity values. The identifying integers are left opaque to programmers in this specification, so an implementation of QL is free to use some other set of countable labels to identify its entities.
Ordering
@@ -458,7 +460,7 @@ For dates, the ordering is chronological.
For floats, the ordering is as specified in IEEE 754 when one exists, except that NaN is considered equal to itself and is ordered after all other floats, and negative zero is considered to be strictly less than positive zero.
For integers, the ordering is as for two's complement integers.
For integers (and :ref:`big integers <bigint>`), the ordering is numerical.
For strings, the ordering is lexicographic.

View File

@@ -10,12 +10,12 @@ Types
QL is a statically typed language, so each variable must have a declared type.
A type is a set of values.
For example, the type ``int`` is the set of integers.
Note that a value can belong to more than one of these sets, which means that it can have more
For example, the type ``int`` is the set of integers.
Note that a value can belong to more than one of these sets, which means that it can have more
than one type.
The kinds of types in QL are :ref:`primitive types <primitive-types>`, :ref:`classes <classes>`,
:ref:`character types <character-types>`, :ref:`class domain types <domain-types>`,
:ref:`character types <character-types>`, :ref:`class domain types <domain-types>`,
:ref:`algebraic datatypes <algebraic-datatypes>`, :ref:`type unions <type-unions>`,
and :ref:`database types <database-types>`.
@@ -31,27 +31,29 @@ independent of the database that you are querying.
.. _boolean:
#. **boolean**: This type contains the values ``true`` and ``false``.
.. _float:
#. **float**: This type contains 64-bit floating point numbers, such as ``6.28`` and ``-0.618``.
.. _int:
#. **int**: This type contains 32-bit `two's complement <https://en.wikipedia.org/wiki/Two%27s_complement>`_ integers, such as ``-1`` and ``42``.
.. _string:
#. **string**: This type contains finite strings of 16-bit characters.
.. _date:
#. **date**: This type contains dates (and optionally times).
#. **date**: This type contains dates (and optionally times).
QL has a range of built-in operations defined on primitive types. These are available by using dispatch on expressions of the appropriate type. For example, ``1.toString()`` is the string representation of the integer constant ``1``. For a full list of built-in operations available in QL, see the
section on `built-ins <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`__ in the QL language specification.
Additionally, there is an experimental arbitrary-precision integer primitive type at :ref:`QlBuiltins::BigInt <bigint>`. This type is not available in the CodeQL CLI by default, but you can enable it by passing the ``--allow-experimental=bigint`` option to the CodeQL CLI.
.. index:: class
.. _classes:
@@ -65,7 +67,7 @@ Classes provide an easy way to reuse and structure code. For example, you can:
- Define :ref:`member predicates <member-predicates>` on those values.
- Define subclasses that :ref:`override member predicates <overriding-member-predicates>`.
A class in QL doesn't "create" a new object, it just represents a logical property. A value is
A class in QL doesn't "create" a new object, it just represents a logical property. A value is
in a particular class if it satisfies that logical property.
.. _defining-a-class:
@@ -75,8 +77,8 @@ Defining a class
To define a class, you write:
#. The keyword ``class``.
#. The name of the class. This is an `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
#. The keyword ``class``.
#. The name of the class. This is an `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
starting with an uppercase letter.
#. The supertypes that the class is derived from via `extends` and/or `instanceof`
#. The :ref:`body of the class <class-bodies>`, enclosed in braces.
@@ -89,11 +91,11 @@ For example:
OneTwoThree() { // characteristic predicate
this = 1 or this = 2 or this = 3
}
string getAString() { // member predicate
result = "One, two or three: " + this.toString()
}
predicate isEven() { // member predicate
this = 2
}
@@ -101,7 +103,7 @@ For example:
This defines a class ``OneTwoThree``, which contains the values ``1``, ``2``, and ``3``. The
:ref:`characteristic predicate <characteristic-predicates>` captures the logical property of
"being one of the integers 1, 2, or 3."
"being one of the integers 1, 2, or 3."
.. index:: extends
@@ -132,12 +134,12 @@ Class bodies
The body of a class can contain:
- A :ref:`characteristic predicate <characteristic-predicates>` declaration.
- Any number of :ref:`member predicate <member-predicates>` declarations.
- Any number of :ref:`field <fields>` declarations.
- Any number of :ref:`field <fields>` declarations.
When you define a class, that class also inherits all non-:ref:`private` member predicates and
fields from its supertypes.
Depending on whether they are final, you can :ref:`override <overriding-member-predicates>` or
Depending on whether they are final, you can :ref:`override <overriding-member-predicates>` or
:ref:`shadow <final-extensions>` those predicates and fields to give them a more specific definition.
.. _characteristic-predicates:
@@ -181,22 +183,22 @@ This call returns ``"ONE, TWO OR THREE: 1"``.
.. pull-quote:: Note
Characteristic predicates and member predicates often use the variable ``this``.
This variable always refers to a member of the class—in this case a value belonging to the
Characteristic predicates and member predicates often use the variable ``this``.
This variable always refers to a member of the class—in this case a value belonging to the
class ``OneTwoThree``.
In the :ref:`characteristic predicate <characteristic-predicates>`, the variable ``this``
In the :ref:`characteristic predicate <characteristic-predicates>`, the variable ``this``
constrains the values that are in the class.
In a :ref:`member predicate <member-predicates>`, ``this`` acts in the same way as any
In a :ref:`member predicate <member-predicates>`, ``this`` acts in the same way as any
other argument to the predicate.
.. index:: field
.. _fields:
.. _fields:
Fields
------
These are variables declared in the body of a class. A class can have any number of field
declarations (that is, variable declarations) within its body. You can use these variables in
declarations (that is, variable declarations) within its body. You can use these variables in
predicate declarations inside the class. Much like the :ref:`variable <this>` ``this``, fields
must be constrained in the :ref:`characteristic predicate <characteristic-predicates>`.
@@ -207,21 +209,21 @@ For example:
class SmallInt extends int {
SmallInt() { this = [1 .. 10] }
}
class DivisibleInt extends SmallInt {
SmallInt divisor; // declaration of the field `divisor`
DivisibleInt() { this % divisor = 0 }
SmallInt getADivisor() { result = divisor }
}
from DivisibleInt i
select i, i.getADivisor()
In this example, the declaration ``SmallInt divisor`` introduces a field ``divisor``, constrains
it in the characteristic predicate, and then uses it in the declaration of the member predicate
``getADivisor``. This is similar to introducing variables in a :ref:`select clause <select-clauses>`
by declaring them in the ``from`` part.
by declaring them in the ``from`` part.
You can also annotate predicates and fields. See the list of :ref:`annotations <annotations-overview>`
that are available.
@@ -231,7 +233,7 @@ that are available.
Concrete classes
================
The classes in the above examples are all **concrete** classes. They are defined by
The classes in the above examples are all **concrete** classes. They are defined by
restricting the values in a larger type. The values in a concrete class are precisely those
values in the intersection of the supertypes that also satisfy the
:ref:`characteristic predicate <characteristic-predicates>` of the class.
@@ -241,32 +243,32 @@ values in the intersection of the supertypes that also satisfy the
Abstract classes
================
A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract** class, is also a restriction of
the values in a larger type. However, an abstract class is defined as the union of its
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract** class, is also a restriction of
the values in a larger type. However, an abstract class is defined as the union of its
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
characteristic predicate of the class itself **and** the characteristic predicate of a subclass.
Note that final extensions are not considered subclasses in this context.
An abstract class is useful if you want to group multiple existing classes together
under a common name. You can then define member predicates on all those classes. You can also
extend predefined abstract classes: for example, if you import a library that contains an
An abstract class is useful if you want to group multiple existing classes together
under a common name. You can then define member predicates on all those classes. You can also
extend predefined abstract classes: for example, if you import a library that contains an
abstract class, you can add more subclasses to it.
**Example**
If you are writing a security query, you may be interested in identifying
all expressions that can be interpreted as SQL queries.
If you are writing a security query, you may be interested in identifying
all expressions that can be interpreted as SQL queries.
You can use the following abstract class to describe these expressions:
.. code-block:: ql
abstract class SqlExpr extends Expr {
...
...
}
Now define various subclasses—one for each kind of database management system. For example, you
can define a subclass ``class PostgresSqlExpr extends SqlExpr``, which contains expressions
passed to some Postgres API that performs a database query.
can define a subclass ``class PostgresSqlExpr extends SqlExpr``, which contains expressions
passed to some Postgres API that performs a database query.
You can define similar subclasses for MySQL and other database management systems.
The abstract class ``SqlExpr`` refers to all of those different expressions. If you want to add
@@ -278,7 +280,7 @@ there is no need to update the queries that rely on it.
You must take care when you add a new subclass to an existing abstract class. Adding a subclass
is not an isolated change, it also extends the abstract class since that is a union of its
subclasses.
subclasses.
.. _overriding-member-predicates:
@@ -288,7 +290,7 @@ Overriding member predicates
If a class inherits a member predicate from a non-final supertype, you can **override** the
inherited definition. You do this by defining a member predicate with the same name and arity
as the inherited predicate, and by adding the ``override`` :ref:`annotation <override>`.
This is useful if you want to refine the predicate to give a more specific result for the
This is useful if you want to refine the predicate to give a more specific result for the
values in the subclass.
For example, extending the class from the :ref:`first example <defining-a-class>`:
@@ -299,7 +301,7 @@ For example, extending the class from the :ref:`first example <defining-a-class>
OneTwo() {
this = 1 or this = 2
}
override string getAString() {
result = "One or two: " + this.toString()
}
@@ -328,7 +330,7 @@ look like this:
| 3 | One, two or three: 3 |
+---+-------------------------+
In QL, unlike other object-oriented languages, different subtypes of the same types don't need to be
In QL, unlike other object-oriented languages, different subtypes of the same types don't need to be
disjoint. For example, you could define another subclass of ``OneTwoThree``, which overlaps
with ``OneTwo``:
@@ -338,14 +340,14 @@ with ``OneTwo``:
TwoThree() {
this = 2 or this = 3
}
override string getAString() {
result = "Two or three: " + this.toString()
}
}
Now the value 2 is included in both class types ``OneTwo`` and ``TwoThree``. Both of these classes
override the original definition of ``getAString()``. There are two new "most specific" definitions,
Now the value 2 is included in both class types ``OneTwo`` and ``TwoThree``. Both of these classes
override the original definition of ``getAString()``. There are two new "most specific" definitions,
so running the above query gives the following results:
+---+-------------------------+
@@ -373,7 +375,7 @@ For example, using the definitions from the above section:
class Two extends OneTwo, TwoThree {}
Any value in the class ``Two`` must satisfy the logical property represented by ``OneTwo``,
Any value in the class ``Two`` must satisfy the logical property represented by ``OneTwo``,
**and** the logical property represented by ``TwoThree``. Here the class ``Two`` contains one
value, namely 2.
@@ -401,12 +403,12 @@ For example, extending the class from the :ref:`first example <defining-a-class>
.. code-block:: ql
final class FinalOneTwoThree = OneTwoThree;
class OneTwoFinalExtension extends FinalOneTwoThree {
OneTwoFinalExtension() {
this = 1 or this = 2
}
string getAString() {
result = "One or two: " + this.toString()
}
@@ -507,19 +509,19 @@ Had ``Bar`` been defined as ``extends Foo``, then ``select any(Foo f).foo()`` wo
Character types and class domain types
**************************************
You can't refer to these types directly, but each class in QL implicitly defines a character
type and a class domain type. (These are rather more subtle concepts and don't appear very
You can't refer to these types directly, but each class in QL implicitly defines a character
type and a class domain type. (These are rather more subtle concepts and don't appear very
often in practical query writing.)
The **character type** of a QL class is the set of values satisfying the :ref:`characteristic
predicate <characteristic-predicates>` of the class.
It is a subset of the domain type. For concrete classes, a value belongs to
the class if, and only if, it is in the character type. For :ref:`abstract classes
The **character type** of a QL class is the set of values satisfying the :ref:`characteristic
predicate <characteristic-predicates>` of the class.
It is a subset of the domain type. For concrete classes, a value belongs to
the class if, and only if, it is in the character type. For :ref:`abstract classes
<abstract-classes>`, a value must also belong to at least one of the subclasses, in addition to
being in the character type.
being in the character type.
The **domain type** of a QL class is the intersection of the character types of all its supertypes, that is, a value
belongs to the domain type if it belongs to every supertype. It occurs as the type of ``this``
belongs to the domain type if it belongs to every supertype. It occurs as the type of ``this``
in the characteristic predicate of a class.
.. index:: newtype
@@ -570,13 +572,13 @@ The branch definitions have the following form:
<BranchName>(<arguments>) { <body> }
- The type name and the branch names must be `identifiers <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
- The type name and the branch names must be `identifiers <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
starting with an uppercase letter. Conventionally, they start with ``T``.
- The different branches of an algebraic datatype are separated by ``or``.
- The arguments to a branch, if any, are :ref:`variable declarations <variable-declarations>`
separated by commas.
- The body of a branch is a :ref:`predicate <predicates>` body. You can omit the branch body, in which case
it defaults to ``any()``.
it defaults to ``any()``.
Note that branch bodies are evaluated fully, so they must be finite. They should be kept small
for good performance.
@@ -586,28 +588,28 @@ For example, the following algebraic datatype has three branches:
newtype T =
Type1(A a, B b) { body(a, b) }
or
or
Type2(C c)
or
or
Type3()
Standard pattern for using algebraic datatypes
==============================================
Algebraic datatypes are different from :ref:`classes <classes>`. In particular, algebraic datatypes don't have a
Algebraic datatypes are different from :ref:`classes <classes>`. In particular, algebraic datatypes don't have a
``toString()`` member predicate, so you can't use them in a :ref:`select clause <select-clauses>`.
Classes are often used to extend algebraic datatypes (and to provide a ``toString()`` predicate).
Classes are often used to extend algebraic datatypes (and to provide a ``toString()`` predicate).
In the standard QL language libraries, this is usually done as follows:
- Define a class ``A`` that extends the algebraic datatype and optionally declares :ref:`abstract`
predicates.
- For each branch type, define a class ``B`` that extends both ``A`` and the branch type,
- For each branch type, define a class ``B`` that extends both ``A`` and the branch type,
and provide a definition for any abstract predicates from ``A``.
- Annotate the algebraic datatype with :ref:`private`, and leave the classes public.
For example, the following code snippet from the CodeQL data-flow library for C# defines classes
for dealing with tainted or untainted values. In this case, it doesn't make sense for
for dealing with tainted or untainted values. In this case, it doesn't make sense for
``TaintType`` to extend a database type. It is part of the taint analysis, not the underlying
program, so it's helpful to extend a new type (namely ``TTaintType``):
@@ -617,24 +619,24 @@ program, so it's helpful to extend a new type (namely ``TTaintType``):
TExactValue()
or
TTaintedValue()
/** Describes how data is tainted. */
class TaintType extends TTaintType {
string toString() {
this = TExactValue() and result = "exact"
or
or
this = TTaintedValue() and result = "tainted"
}
}
/** A taint type where the data is untainted. */
class Untainted extends TaintType, TExactValue {
}
/** A taint type where the data is tainted. */
class Tainted extends TaintType, TTaintedValue {
}
.. _type-unions:
Type unions
@@ -672,7 +674,7 @@ If we had implemented ``DefiniteInitialization`` as a class extension instead, i
.. code-block:: ql
// THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion
// THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion
// DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization!
class DefiniteInitialization extends InitialValueSource {
DefiniteInitialization() {
@@ -692,7 +694,7 @@ Database types are defined in the database schema. This means that they depend o
that you are querying, and vary according to the data you are analyzing.
For example, if you are querying a CodeQL database for a Java project, the database types may
include ``@ifstmt``, representing an if statement in the Java code, and ``@variable``,
include ``@ifstmt``, representing an if statement in the Java code, and ``@variable``,
representing a variable.
.. _type-compatibility:

View File

@@ -0,0 +1,546 @@
/** Auto-generated dbscheme; do not edit. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
compilations(unique int id: @compilation, string cwd: string ref);
#keyset[id, num]
compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
#keyset[id, num, kind]
compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
#keyset[id, num]
compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
string full_error_message: string ref, int location: @location ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref);
folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @namedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int named: @namedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @scopenode | @comment_group | @comment;
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @genericfunctioninstantiationexpr
| 14 = @generictypeinstantiationexpr
| 15 = @sliceexpr
| 16 = @typeassertexpr
| 17 = @callorconversionexpr
| 18 = @starexpr
| 19 = @keyvalueexpr
| 20 = @arraytypeexpr
| 21 = @structtypeexpr
| 22 = @functypeexpr
| 23 = @interfacetypeexpr
| 24 = @maptypeexpr
| 25 = @typesetliteralexpr
| 26 = @plusexpr
| 27 = @minusexpr
| 28 = @notexpr
| 29 = @complementexpr
| 30 = @derefexpr
| 31 = @addressexpr
| 32 = @arrowexpr
| 33 = @lorexpr
| 34 = @landexpr
| 35 = @eqlexpr
| 36 = @neqexpr
| 37 = @lssexpr
| 38 = @leqexpr
| 39 = @gtrexpr
| 40 = @geqexpr
| 41 = @addexpr
| 42 = @subexpr
| 43 = @orexpr
| 44 = @xorexpr
| 45 = @mulexpr
| 46 = @quoexpr
| 47 = @remexpr
| 48 = @shlexpr
| 49 = @shrexpr
| 50 = @andexpr
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @typeparamtype
| 27 = @arraytype
| 28 = @slicetype
| 29 = @structtype
| 30 = @pointertype
| 31 = @interfacetype
| 32 = @tupletype
| 33 = @signaturetype
| 34 = @maptype
| 35 = @sendchantype
| 36 = @recvchantype
| 37 = @sendrcvchantype
| 38 = @namedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @namedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,552 @@
/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
compilations(unique int id: @compilation, string cwd: string ref);
#keyset[id, num]
compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
#keyset[id, num, kind]
compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
#keyset[id, num]
compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
string full_error_message: string ref, int location: @location ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref);
folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @namedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int named: @namedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
#keyset[parent, index]
struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
#keyset[interface, index]
interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @scopenode | @comment_group | @comment;
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @genericfunctioninstantiationexpr
| 14 = @generictypeinstantiationexpr
| 15 = @sliceexpr
| 16 = @typeassertexpr
| 17 = @callorconversionexpr
| 18 = @starexpr
| 19 = @keyvalueexpr
| 20 = @arraytypeexpr
| 21 = @structtypeexpr
| 22 = @functypeexpr
| 23 = @interfacetypeexpr
| 24 = @maptypeexpr
| 25 = @typesetliteralexpr
| 26 = @plusexpr
| 27 = @minusexpr
| 28 = @notexpr
| 29 = @complementexpr
| 30 = @derefexpr
| 31 = @addressexpr
| 32 = @arrowexpr
| 33 = @lorexpr
| 34 = @landexpr
| 35 = @eqlexpr
| 36 = @neqexpr
| 37 = @lssexpr
| 38 = @leqexpr
| 39 = @gtrexpr
| 40 = @geqexpr
| 41 = @addexpr
| 42 = @subexpr
| 43 = @orexpr
| 44 = @xorexpr
| 45 = @mulexpr
| 46 = @quoexpr
| 47 = @remexpr
| 48 = @shlexpr
| 49 = @shrexpr
| 50 = @andexpr
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @typeparamtype
| 27 = @arraytype
| 28 = @slicetype
| 29 = @structtype
| 30 = @pointertype
| 31 = @interfacetype
| 32 = @tupletype
| 33 = @signaturetype
| 34 = @maptype
| 35 = @sendchantype
| 36 = @recvchantype
| 37 = @sendrcvchantype
| 38 = @namedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @namedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,5 @@
description: Remove component-tags and interface-method-id tables
compatibility: full
struct_tags.rel: delete
interface_private_method_ids.rel: delete

View File

@@ -410,7 +410,7 @@ func AddDefaultSnippet(snippet string) bool {
// PrintDbScheme prints the schema of this database to the writer `w`
func PrintDbScheme(w io.Writer) {
fmt.Fprintf(w, "/** Auto-generated dbscheme; do not edit. */\n\n")
fmt.Fprintf(w, "/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */\n\n")
for _, snippet := range defaultSnippets {
fmt.Fprintf(w, "%s\n", snippet)
}

View File

@@ -1150,6 +1150,20 @@ var ComponentTypesTable = NewTable("component_types",
EntityColumn(TypeType, "tp"),
).KeySet("parent", "index")
// StructTagsTable is the table associating struct types with their component types' tags
var StructTagsTable = NewTable("struct_tags",
EntityColumn(StructType, "parent"),
IntColumn("index"),
StringColumn("tag"),
).KeySet("parent", "index")
// InterfacePrivateMethodIdsTable is the table associating interface types with the indices and ids of their private methods.
var InterfacePrivateMethodIdsTable = NewTable("interface_private_method_ids",
EntityColumn(InterfaceType, "interface"),
IntColumn("index"),
StringColumn("id"),
).KeySet("interface", "index")
// ArrayLengthTable is the table associating array types with their length (represented as a string
// since Go array lengths are 64-bit and hence do not always fit into a QL integer)
var ArrayLengthTable = NewTable("array_length",

View File

@@ -1624,6 +1624,9 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
name = ""
}
extractComponentType(tw, lbl, i, name, field.Type())
if tp.Tag(i) != "" {
dbscheme.StructTagsTable.Emit(tw, lbl, i, tp.Tag(i))
}
}
case *types.Pointer:
kind = dbscheme.PointerType.Index()
@@ -1641,6 +1644,10 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
extractMethod(tw, meth)
extractComponentType(tw, lbl, i, meth.Name(), meth.Type())
if !meth.Exported() {
dbscheme.InterfacePrivateMethodIdsTable.Emit(tw, lbl, i, meth.Id())
}
}
for i := 0; i < tp.NumEmbeddeds(); i++ {
component := tp.EmbeddedType(i)

View File

@@ -10,7 +10,7 @@ toolchain go1.23.1
// bazel mod tidy
require (
golang.org/x/mod v0.21.0
golang.org/x/tools v0.25.0
golang.org/x/tools v0.26.0
)
require golang.org/x/sync v0.8.0 // indirect

View File

@@ -2,5 +2,5 @@ golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=

View File

@@ -1,3 +1,7 @@
## 1.0.10
No user-facing changes.
## 1.0.9
No user-facing changes.

View File

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

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