Compare commits

...

462 Commits

Author SHA1 Message Date
Cornelius Riemenschneider
c870c5e3da workaround. 2024-10-22 10:47:46 +02:00
Cornelius Riemenschneider
9d1a1d41de set shell 2024-10-21 15:19:23 +02:00
Cornelius Riemenschneider
4db2c68aee more 2024-10-21 14:53:31 +02:00
Cornelius Riemenschneider
a8060e45fd more debug output. 2024-10-21 14:50:45 +02:00
Cornelius Riemenschneider
de6ae4d92b fix 2024-10-21 14:46:25 +02:00
Cornelius Riemenschneider
0a90ba981e switch runner. 2024-10-21 14:45:15 +02:00
Cornelius Riemenschneider
99547ee165 switch dir 2024-10-21 14:44:14 +02:00
Cornelius Riemenschneider
5c5084aca0 less. 2024-10-21 14:42:30 +02:00
Cornelius Riemenschneider
b343734083 more debug 2024-10-21 14:40:32 +02:00
Cornelius Riemenschneider
5ddccd00e4 debug wf 2024-10-21 14:30:56 +02:00
Cornelius Riemenschneider
ef71cf5d26 debug 2024-10-21 14:27:36 +02:00
Ian Lynagh
196baa99b2 Merge pull request #17769 from igfoo/igfoo/2.1.0-beta2
Kotlin: Fix for 2.1.0-Beta2
2024-10-15 14:56:55 +01:00
Arthur Baars
bdec751527 Merge pull request #17768 from github/post-release-prep/codeql-cli-2.19.2
Post-release preparation for codeql-cli-2.19.2
2024-10-15 15:33:42 +02:00
Paolo Tranquilli
1d9767a163 Merge pull request #17770 from github/redsun82/rust-callable-base
Rust: Add `Callable` as a base class of `Function` and `ClosureExpr`
2024-10-15 15:00:59 +02:00
Jeroen Ketema
50ec2549c0 Merge pull request #17740 from jketema/requires
C++: Add support for C++ requires expressions
2024-10-15 14:32:28 +02:00
Paolo Tranquilli
bd08bc7923 Rust: address review 2024-10-15 14:21:11 +02:00
Ian Lynagh
b5bfd06624 Kotlin: Fix for 2.1.0-Beta2
We need to catch a different exception now.
2024-10-15 13:17:26 +01:00
github-actions[bot]
079ab77a38 Post-release preparation for codeql-cli-2.19.2 2024-10-15 12:16:59 +00: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
Jeroen Ketema
168f7f5d34 C++: Add support for C++ requires expressions 2024-10-15 13:44:17 +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
Ian Lynagh
24d98eef83 Merge pull request #17741 from github/igfoo/logverb
Kotlin: Log our verbosity level
2024-10-15 11:42:15 +01: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
Paolo Tranquilli
248eb7f00c Merge branch 'main' into rust/callable-base 2024-10-15 11:03:11 +02: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
Ian Lynagh
9f340279cb Kotlin: Accept test changes 2024-10-11 15:10:19 +01: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
Ian Lynagh
156ddd3fae Kotlin: Log our verbosity level
This happens at `info` level, which is logged by default.
2024-10-11 14:24:25 +01: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
Tom Hvitved
0ec40afa4c Rust: Update expected test output 2024-10-11 12:44:35 +02:00
Tom Hvitved
8cc349e85f Rust: Run codegen 2024-10-11 12:01:16 +02:00
Tom Hvitved
b284a2a7c0 Rust: Add Callable as a base class of Function and ClosureExpr 2024-10-11 12:00:30 +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
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
Geoffrey White
f7db47b771 Merge pull request #17588 from geoffw0/loc2
Rust: Improve lines-of-code counts.
2024-10-02 18:13:36 +01:00
Geoffrey White
0b6ec4624e Rust: Autoformat. 2024-10-02 17:05:01 +01:00
Geoffrey White
d6848f5c5d Rust: Apparently a doc comment here was illegal. 2024-10-02 17:00:28 +01:00
Geoffrey White
01abcf8537 Rust: Use just end locations for now, to avoid all false positive lines caused by attached comments. 2024-10-02 16:54:02 +01:00
Geoffrey White
8c87b66bea Rust: Add more test cases for comments. 2024-10-02 16:52:19 +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
Tom Hvitved
d6415cd0c8 Merge pull request #17642 from hvitved/rust/unused-variable
Rust: Implement `UnusedVariable.ql`
2024-10-02 15:41:24 +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
Tom Hvitved
3a1f6efce4 Address review comments 2024-10-02 13:37:24 +02:00
Geoffrey White
8243f87179 Rust: Modify the exclusion as suggested in comments. 2024-10-02 11:38:29 +01:00
Tom Hvitved
fb9ec2423c Rust: Implement UnusedVariable.ql 2024-10-02 11:22:32 +02:00
Tom Hvitved
3fa52ad680 Merge pull request #17633 from hvitved/rust/cfg-fixes
Rust: More CFG modelling
2024-10-02 11:21:53 +02:00
Tom Hvitved
9c7216fe4f Rust: Add another CFG test 2024-10-02 10:59:26 +02:00
Tom Hvitved
69e0ad0181 Rust: Refactor CFG implementation for loops 2024-10-02 10:55:52 +02:00
Calum Grant
8b536f54fd Merge pull request #17481 from github/calumgrant/bmn/uninitialized-local
C++: Remove FPs from cpp/uninitialized-local when encountered extraction errors
2024-10-02 09:29:15 +01:00
Calum Grant
d3695dce4d C++: Add change note 2024-10-02 08:14:23 +01: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
Tom Hvitved
8f0b7f0969 Rust: Use propagatesAbnormal in two places 2024-10-01 21:49:08 +02:00
Tom Hvitved
c4eafb2cf3 Rust: Skip ParenExprs in the CFG 2024-10-01 21:26:49 +02:00
Tom Hvitved
8b66dc16ad Rust: Fix CFG for labelled block expressions 2024-10-01 21:03:36 +02:00
Tom Hvitved
e8cb3490e6 Rust: Refine deadEnd consistency check 2024-10-01 21:02:55 +02:00
Tom Hvitved
85957767c9 Rust: Fix CFG for while let loops 2024-10-01 21:02:17 +02:00
Tom Hvitved
071076875c Rust: Make more CFG nodes leaves 2024-10-01 21:01:56 +02:00
Tom Hvitved
26c69b8f8a Rust: Add more CFG tests 2024-10-01 21:01:49 +02:00
Tom Hvitved
bbd0aa929f Rust: Add more missing CFG trees 2024-10-01 21:01:26 +02:00
Tom Hvitved
17770af491 Rust: Account for let statement else blocks in deadEnd 2024-10-01 21:00:39 +02:00
Tom Hvitved
a507854288 Rust: Fix bug in BooleanCompletion.isValidForSpecific0 2024-10-01 21:00:33 +02:00
Tom Hvitved
8c1fd8fa7a Rust: Implement CFG for ForExprs 2024-10-01 21:00:09 +02:00
Tom Hvitved
f3e3734424 Rust: Implement CFG for WhileExprs 2024-10-01 20:59:41 +02:00
Tom Hvitved
5444a5bf8a Rust: Extend while and for CFG tests 2024-10-01 20:59:13 +02:00
Geoffrey White
3a54c10f36 Rust: For now exclude top-level AST elements from LOC counts. This is not ideal. 2024-10-01 17:35:30 +01:00
Tom Hvitved
5fb61b0304 Merge pull request #17606 from hvitved/rust/variables 2024-10-01 18:13:32 +02:00
Ian Lynagh
6af5afc184 Merge pull request #17634 from igfoo/igfoo/implicit_param_name
Java: Add a test for parameter names
2024-10-01 17:03:18 +01:00
Calum Grant
cd1f10cdea C++: Reinstate accidentally-deleted comment 2024-10-01 16:15:24 +01:00
Geoffrey White
74826032ef Merge branch 'main' into loc2 and accept new test results. 2024-10-01 16:10:39 +01: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
Calum Grant
a9b3c0d91b C++: Address review comments 2024-10-01 15:47:12 +01:00
Rasmus Lerchedahl Petersen
38b1eb7c71 Python: just use ListElementContent for iterables 2024-10-01 16:24:15 +02:00
Ian Lynagh
323b7cb96f Java: Follow change of implicit parameter names 2024-10-01 15:06:45 +01:00
Ian Lynagh
901f756c69 Java: Add a test for parameter names 2024-10-01 15:06:42 +01:00
Chris Smowton
01c9509741 Merge pull request #17628 from smowton/smowton/admin/go-vendor-dir-extraction-option
Go: add extractor option for vendor-directory extraction
2024-10-01 14:47:42 +01:00
Anders Schack-Mulligen
6081ba5902 Merge pull request #17604 from aschackmull/java/neutral-overrides
Java/C#: Add overrides to the interpretation of neutral MaD models.
2024-10-01 14:55:54 +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
Tom Hvitved
91e26d0f44 Rust: Add another variable test 2024-10-01 13:45:58 +02:00
Tom Hvitved
a172063e6a Rust: Document VariableOrAccessCand 2024-10-01 13:38:18 +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
Calum Grant
fe00c8819d C++: Fix formatting 2024-10-01 11:26:47 +01:00
Chris Smowton
cb0b388345 Merge pull request #17630 from smowton/smowton/admin/deduplicate-tests
Go: deduplicate integration tests
2024-10-01 11:08:00 +01:00
Calum Grant
4712ae1cfc C++: Use refactored isFirstAllocatorCallArgument() 2024-10-01 11:01:51 +01:00
Calum Grant
59a77d70c0 C++: Use Function::hasErrors in queries 2024-10-01 11:01:23 +01:00
Calum Grant
4b5aa1497b C++: Implement Function::hasErrors() 2024-10-01 11:00:44 +01: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
Chris Smowton
d689db23d8 Warn on use of old option 2024-10-01 10:43:28 +01: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
Calum Grant
60abea17e6 C++: Test for cpp/uninitialized-local 2024-10-01 10:32:17 +01:00
Jeroen Ketema
66d156d386 Merge pull request #17608 from jketema/macro-expansion-tests
C++: Add more macro expansion tests
2024-10-01 11:19:49 +02:00
Rasmus Lerchedahl Petersen
e0a3c8a1c4 Python: add change note 2024-10-01 10:12:39 +02:00
Tom Hvitved
b0efffd8f0 Rust: AST support for variables 2024-10-01 10:10:08 +02:00
Rasmus Lerchedahl Petersen
bd68986fa4 Python: add test showing dict can take multiple arguments 2024-10-01 10:01:22 +02:00
Tom Hvitved
a282efc43e Rust: Add inline test expectations library 2024-10-01 09:50:05 +02:00
Tom Hvitved
1d6626c821 Rust: Implement IdentPat.toString() 2024-10-01 08:42:26 +02:00
Jeroen Ketema
2427227b84 Merge pull request #17611 from microsoft/brodes/wcharcharconversion_false_positives_upstream5
Brodes/wcharcharconversion false positives upstream5
2024-10-01 08:00:51 +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
Angela P Wen
204e4c5bb0 Merge pull request #17631 from github/post-release-prep/codeql-cli-2.19.1
Post-release preparation for codeql-cli-2.19.1
2024-09-30 13:47:39 -07:00
github-actions[bot]
e97878ed63 Post-release preparation for codeql-cli-2.19.1 2024-09-30 19:49:00 +00:00
Chris Smowton
be389b4c19 Go: deduplicate integration tests 2024-09-30 19:54:14 +01:00
Chris Smowton
c9d6c80913 Log when vendor dir extraction is active 2024-09-30 18:44:20 +01:00
Chris Smowton
684aedf6aa Golang vendor dir extraction: add extractor option 2024-09-30 18:24:49 +01:00
REDMOND\brodes
c496503053 Formatting. 2024-09-30 11:23:08 -04:00
REDMOND\brodes
eeddb176f8 Merge branch 'brodes/wcharcharconversion_false_positives_upstream5' of https://github.com/microsoft/codeql into brodes/wcharcharconversion_false_positives_upstream5 2024-09-30 11:20:20 -04:00
REDMOND\brodes
162519185d Removing unnecessary bracket/singleton set literal. 2024-09-30 11:19:31 -04:00
Ben Rodes
9e9469f3ca Update cpp/ql/src/change-notes/2024-09-26-wcharcharconversion-false-positives.md
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2024-09-30 11:17:48 -04:00
REDMOND\brodes
318e75c094 Changing name of predicate to be clearer, and removing an unused parameter. 2024-09-30 11:10:28 -04:00
REDMOND\brodes
c91f7f4918 Altering exists predicate ordering to be clearer. 2024-09-30 11:07:09 -04:00
REDMOND\brodes
31324fc778 Altering ordering for exists statement to be clearer. 2024-09-30 11:05:38 -04:00
REDMOND\brodes
51e787b316 Switching to looking for explicit declaration of unsigned char, to avoid cases where unsigned char is the default char width for char. 2024-09-30 11:02:43 -04:00
REDMOND\brodes
c4737c7fbb Changing from hasIntermediateType to getABaseType. 2024-09-30 10:58:45 -04:00
REDMOND\brodes
338ab96593 Correct comment. 2024-09-30 10:46:39 -04:00
Anders Schack-Mulligen
5c4b4d644a C#: Accept test changes. 2024-09-30 16:27:50 +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
Anders Schack-Mulligen
a8f55d93cb C#: Add overrides to the interpretation of neutral MaD models. 2024-09-30 15:23:27 +02:00
Anders Schack-Mulligen
0459d136d3 Java: Remove neutral model for Object.toString. 2024-09-30 15:17:21 +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
Anders Schack-Mulligen
ec0bd4494c Java: Add overrides to the interpretation of neutral MaD models. 2024-09-30 13:11:49 +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
Jeroen Ketema
e73d1c7b76 C++: Add more macro expansion tests 2024-09-28 22:32:36 +02:00
REDMOND\brodes
b73fe0ba0a Adding change log 2024-09-27 12:41:45 -04:00
REDMOND\brodes
92c8d39ba3 Updating expected file, false positives now resolved. 2024-09-27 12:39:50 -04:00
REDMOND\brodes
cc24f1ed9f Modifications to the query to address false positives. 2024-09-27 12:38:22 -04:00
REDMOND\brodes
26e58532ee Adding tests and updated expected file with false positives to correct. 2024-09-27 12:37:09 -04: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
Geoffrey White
caca4950e6 Rust: Revert the change to FileSystem.qll. 2024-09-26 11:10:32 +01:00
Geoffrey White
f8ce11b3a7 Rust: Improve File.getNumberOfLinesOfCode(). 2024-09-25 16:42:29 +01:00
Geoffrey White
7da2845cad Rust: Uncomment two lines from the test that should now behave deterministically. 2024-09-25 16:42:28 +01: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
773 changed files with 46793 additions and 10804 deletions

View File

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

View File

@@ -10,26 +10,35 @@ on:
- MODULE.bazel - MODULE.bazel
- .bazelrc - .bazelrc
- misc/bazel/** - misc/bazel/**
push:
branches:
- criemen/debug
permissions: permissions:
contents: read contents: read
jobs: jobs:
test-mac:
name: Test MacOS
runs-on: macos-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Run tests
uses: ./go/actions/test
test-win: test-win:
if: github.repository_owner == 'github'
name: Test Windows name: Test Windows
runs-on: windows-latest-xl runs-on: windows-latest
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Run tests with:
uses: ./go/actions/test sparse-checkout: go
- name: dump env bash
shell: bash
run: |
set -x
cd go
type -a bazel
where bazel
echo $PATH
bazel version
- name: Test
shell: bash
run: |
cd go
make gen
# - name: Run tests
# uses: ./go/actions/test

22
Cargo.lock generated
View File

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

View File

@@ -7,7 +7,7 @@ members = [
"ruby/extractor", "ruby/extractor",
"rust/extractor", "rust/extractor",
"rust/extractor/macros", "rust/extractor/macros",
"rust/generate-schema", "rust/ast-generator",
] ]
[patch.crates-io] [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 = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0") 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 = "gazelle", version = "0.38.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1") bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.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) bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
@@ -61,7 +61,7 @@ r.from_cargo(
"//ruby/extractor:Cargo.toml", "//ruby/extractor:Cargo.toml",
"//rust/extractor:Cargo.toml", "//rust/extractor:Cargo.toml",
"//rust/extractor/macros:Cargo.toml", "//rust/extractor/macros:Cargo.toml",
"//rust/generate-schema:Cargo.toml", "//rust/ast-generator:Cargo.toml",
"//shared/tree-sitter-extractor: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

@@ -0,0 +1,17 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprRequirement(Expr expr) {
exists(int kind | exprs(expr, kind, _) | kind = [391, 392, 393])
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprRequirement(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
class Parameter extends @parameter {
string toString() { none() }
}
class ParameterizedElement extends @parameterized_element {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
from Parameter param, ParameterizedElement pe, int index, Type type
where
params(param, pe, index, type) and
not pe instanceof @requires_expr
select param, pe, index, type

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
description: Support C++20 requires expressions
compatibility: partial
compound_requirement_is_noexcept.rel: delete
exprs.rel: run exprs.qlo
params.rel: run params.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 ## 2.0.1
No user-facing changes. No user-facing changes.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.

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.Linkage
import semmle.code.cpp.Location import semmle.code.cpp.Location
import semmle.code.cpp.Compilation import semmle.code.cpp.Compilation
import semmle.code.cpp.Concept
import semmle.code.cpp.Element import semmle.code.cpp.Element
import semmle.code.cpp.Namespace import semmle.code.cpp.Namespace
import semmle.code.cpp.Specifier import semmle.code.cpp.Specifier

View File

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

View File

@@ -0,0 +1,161 @@
/**
* Provides classes for working with C++ concepts.
*/
import semmle.code.cpp.exprs.Expr
/**
* A C++ requires expression.
*
* For example, with `T` and `U` template parameters:
* ```cpp
* requires (T x, U y) { x + y; };
* ```
*/
class RequiresExpr extends Expr, @requires_expr {
override string toString() {
if exists(this.getAParameter())
then result = "requires(...) { ... }"
else result = "requires { ... }"
}
override string getAPrimaryQlClass() { result = "RequiresExpr" }
/**
* Gets a requirement in this requires expression.
*/
RequirementExpr getARequirement() { result = this.getAChild() }
/**
* Gets the nth requirement in this requires expression.
*/
RequirementExpr getRequirement(int n) { result = this.getChild(n) }
/**
* Gets the number of requirements in this requires expression.
*/
int getNumberOfRequirements() { result = count(this.getARequirement()) }
/**
* Gets a parameter of this requires expression, if any.
*/
Parameter getAParameter() { result.getRequiresExpr() = underlyingElement(this) }
/**
* Gets the the nth parameter of this requires expression.
*/
Parameter getParameter(int n) {
result.getRequiresExpr() = underlyingElement(this) and result.getIndex() = n
}
/**
* Gets the number of parameters of this requires expression.
*/
int getNumberOfParameters() { result = count(this.getAParameter()) }
}
/**
* A C++ requirement in a requires expression.
*/
class RequirementExpr extends Expr { }
/**
* A C++ simple requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires(T x, U y) { x + y; };
* ```
* with `T` and `U` template parameters, then `x + y;` is a simple requirement.
*/
class SimpleRequirementExpr extends RequirementExpr {
SimpleRequirementExpr() {
this.getParent() instanceof RequiresExpr and
not this instanceof TypeRequirementExpr and
not this instanceof CompoundRequirementExpr and
not this instanceof NestedRequirementExpr
}
override string getAPrimaryQlClass() { result = "SimpleRequirementExpr" }
}
/**
* A C++ type requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires { typename T::a_field; };
* ```
* with `T` a template parameter, then `typename T::a_field;` is a type requirement.
*/
class TypeRequirementExpr extends RequirementExpr, TypeName {
TypeRequirementExpr() { this.getParent() instanceof RequiresExpr }
override string getAPrimaryQlClass() { result = "TypeRequirementExpr" }
}
/**
* A C++ compound requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires(T x) { { x } noexcept -> std::same_as<int>; };
* ```
* with `T` a template parameter, then `{ x } noexcept -> std::same_as<int>;` is
* a compound requirement.
*/
class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
override string toString() {
if exists(this.getReturnTypeRequirement())
then result = "{ ... } -> ..."
else result = "{ ... }"
}
override string getAPrimaryQlClass() { result = "CompoundRequirementExpr" }
/**
* Gets the expression from the compound requirement.
*/
Expr getExpr() { result = this.getChild(0) }
/**
* Gets the return type requirement from the compound requirement, if any.
*/
Expr getReturnTypeRequirement() { result = this.getChild(1) }
/**
* Holds if the expression from the compound requirement must not be
* potentially throwing.
*/
predicate isNoExcept() { compound_requirement_is_noexcept(underlyingElement(this)) }
}
/**
* A C++ nested requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires { requires std::is_same<T, int>::value; };
* ```
* with `T` a template parameter, then `requires std::is_same<T, int>::value;` is
* a nested requirement.
*/
class NestedRequirementExpr extends Expr, @nested_requirement {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
/**
* Gets the constraint from the nested requirement.
*/
Expr getConstraint() { result = this.getChild(0) }
}
/**
* A C++ concept id expression.
*/
class ConceptIdExpr extends RequirementExpr, @concept_id {
override string toString() { result = "concept<...>" }
override string getAPrimaryQlClass() { result = "ConceptIdExpr" }
}

View File

@@ -500,6 +500,17 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Gets the nearest enclosing AccessHolder. * Gets the nearest enclosing AccessHolder.
*/ */
override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() } override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() }
/**
* Holds if this function has extraction errors that create an `ErrorExpr`.
*/
predicate hasErrors() {
exists(ErrorExpr e |
e.getEnclosingFunction() = this and
// Exclude the first allocator call argument because it is always extracted as `ErrorExpr`.
not exists(NewOrNewArrayExpr new | e = new.getAllocatorCall().getArgument(0))
)
}
} }
pragma[noinline] pragma[noinline]

View File

@@ -7,8 +7,8 @@ import semmle.code.cpp.Declaration
private import semmle.code.cpp.internal.ResolveClass private import semmle.code.cpp.internal.ResolveClass
/** /**
* A C/C++ function parameter or catch block parameter. For example the * A C/C++ function parameter, catch block parameter, or requires expression parameter.
* function parameter `p` and the catch block parameter `e` in the following * For example the function parameter `p` and the catch block parameter `e` in the following
* code: * code:
* ``` * ```
* void myFunction(int p) { * void myFunction(int p) {
@@ -20,8 +20,8 @@ private import semmle.code.cpp.internal.ResolveClass
* } * }
* ``` * ```
* *
* For catch block parameters, there is a one-to-one correspondence between * For catch block parameters and expression , there is a one-to-one
* the `Parameter` and its `ParameterDeclarationEntry`. * correspondence between the `Parameter` and its `VariableDeclarationEntry`.
* *
* For function parameters, there is a one-to-many relationship between * For function parameters, there is a one-to-many relationship between
* `Parameter` and `ParameterDeclarationEntry`, because one function can * `Parameter` and `ParameterDeclarationEntry`, because one function can
@@ -118,6 +118,12 @@ class Parameter extends LocalScopeVariable, @parameter {
*/ */
BlockStmt getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) } BlockStmt getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the requires expression to which the parameter belongs, if it is a
* requires expression parameter.
*/
RequiresExpr getRequiresExpr() { params(underlyingElement(this), unresolveElement(result), _, _) }
/** /**
* Gets the zero-based index of this parameter. * Gets the zero-based index of this parameter.
* *

View File

@@ -80,6 +80,10 @@ private Declaration getAnEnclosingDeclaration(Locatable ast) {
or or
result = ast.(Parameter).getFunction() result = ast.(Parameter).getFunction()
or or
result = ast.(Parameter).getCatchBlock().getEnclosingFunction()
or
result = ast.(Parameter).getRequiresExpr().getEnclosingFunction()
or
result = ast.(Expr).getEnclosingDeclaration() result = ast.(Expr).getEnclosingDeclaration()
or or
result = ast.(Initializer).getDeclaration() result = ast.(Initializer).getDeclaration()
@@ -99,7 +103,10 @@ private newtype TPrintAstNode =
stmt.getADeclarationEntry() = entry and stmt.getADeclarationEntry() = entry and
shouldPrintDeclaration(stmt.getEnclosingFunction()) shouldPrintDeclaration(stmt.getEnclosingFunction())
} or } or
TParametersNode(Function func) { shouldPrintDeclaration(func) } or TFunctionParametersNode(Function func) { shouldPrintDeclaration(func) } or
TRequiresExprParametersNode(RequiresExpr req) {
shouldPrintDeclaration(getAnEnclosingDeclaration(req))
} or
TConstructorInitializersNode(Constructor ctor) { TConstructorInitializersNode(Constructor ctor) {
ctor.hasEntryPoint() and ctor.hasEntryPoint() and
shouldPrintDeclaration(ctor) shouldPrintDeclaration(ctor)
@@ -303,14 +310,14 @@ class ExprNode extends AstNode {
ExprNode() { expr = ast } ExprNode() { expr = ast }
override AstNode getChildInternal(int childIndex) { override PrintAstNode getChildInternal(int childIndex) {
result.getAst() = expr.getChild(childIndex) result.(AstNode).getAst() = expr.getChild(childIndex)
or or
childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and
result.getAst() = expr.(ConditionDeclExpr).getInitializingExpr() result.(AstNode).getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
or or
exists(int destructorIndex | exists(int destructorIndex |
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and result.(AstNode).getAst() = expr.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2 childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2
) )
} }
@@ -329,7 +336,8 @@ class ExprNode extends AstNode {
} }
override string getChildAccessorPredicateInternal(int childIndex) { override string getChildAccessorPredicateInternal(int childIndex) {
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst()) result =
getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).(AstNode).getAst())
} }
/** /**
@@ -409,6 +417,26 @@ class StmtExprNode extends ExprNode {
} }
} }
/**
* A node representing a `RequiresExpr`
*/
class RequiresExprNode extends ExprNode {
override RequiresExpr expr;
override PrintAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
childIndex = -1 and
result.(RequiresExprParametersNode).getRequiresExpr() = expr
}
override string getChildAccessorPredicateInternal(int childIndex) {
result = super.getChildAccessorPredicateInternal(childIndex)
or
childIndex = -1 and result = "<params>"
}
}
/** /**
* A node representing a `DeclarationEntry`. * A node representing a `DeclarationEntry`.
*/ */
@@ -510,6 +538,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`. * A node representing a `Parameter`.
*/ */
@@ -552,10 +596,10 @@ class InitializerNode extends AstNode {
/** /**
* A node representing the parameters of a `Function`. * A node representing the parameters of a `Function`.
*/ */
class ParametersNode extends PrintAstNode, TParametersNode { class FunctionParametersNode extends PrintAstNode, TFunctionParametersNode {
Function func; Function func;
ParametersNode() { this = TParametersNode(func) } FunctionParametersNode() { this = TFunctionParametersNode(func) }
final override string toString() { result = "" } final override string toString() { result = "" }
@@ -576,6 +620,33 @@ class ParametersNode extends PrintAstNode, TParametersNode {
final Function getFunction() { result = func } final Function getFunction() { result = func }
} }
/**
* A node representing the parameters of a `RequiresExpr`.
*/
class RequiresExprParametersNode extends PrintAstNode, TRequiresExprParametersNode {
RequiresExpr req;
RequiresExprParametersNode() { this = TRequiresExprParametersNode(req) }
final override string toString() { result = "" }
final override Location getLocation() { result = getRepresentativeLocation(req) }
override AstNode getChildInternal(int childIndex) {
result.getAst() = req.getParameter(childIndex)
}
override string getChildAccessorPredicateInternal(int childIndex) {
exists(this.getChildInternal(childIndex)) and
result = "getParameter(" + childIndex.toString() + ")"
}
/**
* Gets the `RequiresExpr` for which this node represents the parameters.
*/
final RequiresExpr getRequiresExpr() { result = req }
}
/** /**
* A node representing the initializer list of a `Constructor`. * A node representing the initializer list of a `Constructor`.
*/ */
@@ -679,7 +750,7 @@ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
override PrintAstNode getChildInternal(int childIndex) { override PrintAstNode getChildInternal(int childIndex) {
childIndex = 0 and childIndex = 0 and
result.(ParametersNode).getFunction() = func result.(FunctionParametersNode).getFunction() = func
or or
childIndex = 1 and childIndex = 1 and
result.(ConstructorInitializersNode).getConstructor() = func result.(ConstructorInitializersNode).getConstructor() = func
@@ -754,6 +825,8 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or or
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()" s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
or or
s.(Handler).getParameter() = e and pred = "getParameter()"
or
s.(IfStmt).getInitialization() = e and pred = "getInitialization()" s.(IfStmt).getInitialization() = e and pred = "getInitialization()"
or or
s.(IfStmt).getCondition() = e and pred = "getCondition()" s.(IfStmt).getCondition() = e and pred = "getCondition()"
@@ -901,6 +974,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or or
expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()" expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()"
or or
expr.(CompoundRequirementExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(CompoundRequirementExpr).getReturnTypeRequirement() = ele and
pred = "getReturnTypeRequirement()"
or
expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()" expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()"
or or
expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()" expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()"
@@ -921,6 +999,8 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or or
expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()" expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()"
or or
expr.(NestedRequirementExpr).getConstraint() = ele and pred = "getConstraint()"
or
expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()" expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
or or
expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()" expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()"
@@ -960,6 +1040,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or or
expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()" expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()"
or or
exists(int n |
expr.(RequiresExpr).getRequirement(n) = ele and
pred = "getRequirement(" + n + ")"
)
or
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()" expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or or
expr.(StmtExpr).getStmt() = ele and pred = "getStmt()" expr.(StmtExpr).getStmt() = ele and pred = "getStmt()"

View File

@@ -181,12 +181,7 @@ class VariableDeclarationEntry extends @var_decl {
string getName() { var_decls(this, _, _, result, _) and result != "" } string getName() { var_decls(this, _, _, result, _) and result != "" }
} }
class Parameter extends LocalScopeVariable, @parameter { class Parameter extends LocalScopeVariable, @parameter { }
@functionorblock function;
int index;
Parameter() { params(this, function, index, _) }
}
class GlobalOrNamespaceVariable extends Variable, @globalvariable { } class GlobalOrNamespaceVariable extends Variable, @globalvariable { }

View File

@@ -6,6 +6,112 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends * uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump. * 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 private import internal.IRInternal

View File

@@ -6,6 +6,112 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends * uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump. * 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 private import internal.IRInternal

View File

@@ -6,6 +6,112 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends * uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump. * 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 private import internal.IRInternal

View File

@@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.SideEffect
/** The function `fopen` and friends. */ /** The function `fopen` and friends. */
private class Fopen extends Function, AliasFunction, SideEffectFunction { private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFunction {
Fopen() { Fopen() {
this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"]) this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"])
or or
@@ -47,4 +47,22 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction {
i = 0 and i = 0 and
buffer = true 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 * Holds if `expr` is effectively a multiplication of `operand` with the
* positive constant `positive`. * positive constant `positive`.
@@ -287,6 +318,8 @@ private predicate analyzableExpr(Expr e) {
or or
e instanceof RemExpr e instanceof RemExpr
or or
e instanceof AnalyzableCallToGetc
or
// A conversion is analyzable, provided that its child has an arithmetic // A conversion is analyzable, provided that its child has an arithmetic
// type. (Sometimes the child is a reference type, and so does not get // 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 // any bounds.) Rather than checking whether the type of the child is
@@ -861,6 +894,14 @@ private float getLowerBoundsImpl(Expr expr) {
) )
) )
or 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 // 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 // lower bound of the child. We do not need to handle truncation and
// overflow here, because that is done in `getTruncatedLowerBounds`. // overflow here, because that is done in `getTruncatedLowerBounds`.
@@ -1055,6 +1096,14 @@ private float getUpperBoundsImpl(Expr expr) {
) )
) )
or 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 // 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 // upper bound of the child. We do not need to handle truncation and
// overflow here, because that is done in `getTruncatedUpperBounds`. // overflow here, because that is done in `getTruncatedUpperBounds`.

View File

@@ -534,7 +534,7 @@ static_asserts(
#keyset[function, index, type_id] #keyset[function, index, type_id]
params( params(
int id: @parameter, int id: @parameter,
int function: @functionorblock ref, int function: @parameterized_element ref,
int index: int ref, int index: int ref,
int type_id: @type ref int type_id: @type ref
); );
@@ -1790,6 +1790,10 @@ case @expr.kind of
| 387 = @istriviallyrelocatable | 387 = @istriviallyrelocatable
| 388 = @datasizeof | 388 = @datasizeof
| 389 = @c11_generic | 389 = @c11_generic
| 390 = @requires_expr
| 391 = @nested_requirement
| 392 = @compound_requirement
| 393 = @concept_id
; ;
@var_args_expr = @vastartexpr @var_args_expr = @vastartexpr
@@ -1908,6 +1912,10 @@ case @expr.kind of
| @istriviallyrelocatable | @istriviallyrelocatable
; ;
compound_requirement_is_noexcept(
int expr: @compound_requirement ref
);
new_allocated_type( new_allocated_type(
unique int expr: @new_expr ref, unique int expr: @new_expr ref,
int type_id: @type ref int type_id: @type ref
@@ -2167,11 +2175,11 @@ stmt_decl_entry_bind(
int decl_entry: @element ref int decl_entry: @element ref
); );
@functionorblock = @function | @stmt_block; @parameterized_element = @function | @stmt_block | @requires_expr;
blockscope( blockscope(
unique int block: @stmt_block ref, unique int block: @stmt_block ref,
int enclosing: @functionorblock ref int enclosing: @parameterized_element ref
); );
@jump = @stmt_goto | @stmt_break | @stmt_continue; @jump = @stmt_goto | @stmt_break | @stmt_continue;

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: Support C++20 requires expressions
compatibility: backwards

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -57,5 +57,5 @@ where
not declarationHasSideEffects(v) and not declarationHasSideEffects(v) and
not exists(AsmStmt s | f = s.getEnclosingFunction()) and not exists(AsmStmt s | f = s.getEnclosingFunction()) and
not v.getAnAttribute().getName() = "unused" and not v.getAnAttribute().getName() = "unused" and
not any(ErrorExpr e).getEnclosingFunction() = f // unextracted expr may use `v` not f.hasErrors() // Unextracted expressions may use `v`
select v, "Variable " + v.getName() + " is not used." select v, "Variable " + v.getName() + " is not used."

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 ## 1.2.4
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -29,7 +29,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
override predicate isSource(Instruction source) { override predicate isSource(Instruction source) {
exists(Function func | exists(Function func |
// Rule out FPs caused by extraction errors. // Rule out FPs caused by extraction errors.
not any(ErrorExpr e).getEnclosingFunction() = func and not func.hasErrors() and
not intentionallyReturnsStackPointer(func) and not intentionallyReturnsStackPointer(func) and
func = source.getEnclosingFunction() func = source.getEnclosingFunction()
| |

View File

@@ -65,6 +65,7 @@ predicate isSinkImpl(Instruction sink, VariableAccess va) {
exists(LoadInstruction load | exists(LoadInstruction load |
va = load.getUnconvertedResultExpression() and va = load.getUnconvertedResultExpression() and
not va = commonException() and not va = commonException() and
not va.getTarget().(LocalVariable).getFunction().hasErrors() and
sink = load.getSourceValue() sink = load.getSourceValue()
) )
} }

View File

@@ -24,7 +24,7 @@ predicate instructionHasVariable(VariableAddressInstruction vai, StackVariable v
// Pointer-to-member types aren't properly handled in the dbscheme. // Pointer-to-member types aren't properly handled in the dbscheme.
not vai.getResultType() instanceof PointerToMemberType and not vai.getResultType() instanceof PointerToMemberType and
// Rule out FPs caused by extraction errors. // Rule out FPs caused by extraction errors.
not any(ErrorExpr e).getEnclosingFunction() = f not f.hasErrors()
} }
/** /**

View File

@@ -14,102 +14,56 @@
import cpp import cpp
import semmle.code.cpp.controlflow.IRGuards import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources import semmle.code.cpp.security.FlowSources as FS
import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import ImproperArrayIndexValidation::PathGraph import ImproperArrayIndexValidation::PathGraph
import semmle.code.cpp.security.Security
predicate hasUpperBound(VariableAccess offsetExpr) { predicate isFlowSource(FS::FlowSource source, string sourceType) {
exists(BasicBlock controlled, StackVariable offsetVar, SsaDefinition def | sourceType = source.getSourceType()
controlled.contains(offsetExpr) and }
linearBoundControls(controlled, def, offsetVar) and
offsetExpr = def.getAUse(offsetVar) 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) { * Holds if `arrayExpr` accesses an `ArrayType` with a constant size `N`, and
exists(GuardCondition guard, boolean branch | * the value of `offsetExpr` is known to be smaller than `N`.
guard.controls(controlled, branch) and */
cmpWithLinearBound(guard, def.getAUse(offsetVar), Lesser(), branch) 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 { module ImproperArrayIndexValidationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isFlowSource(source, _) } predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
predicate isBarrier(DataFlow::Node node) { predicate isBarrier(DataFlow::Node node) {
hasUpperBound(node.asExpr()) node = DataFlow::BarrierGuard<guardChecks/3>::getABarrierNode()
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
)
} }
predicate isBarrierOut(DataFlow::Node node) { isSink(node) }
predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(ArrayExpr arrayExpr, VariableAccess offsetExpr | exists(ArrayExpr arrayExpr, VariableAccess offsetExpr |
offsetExpr = arrayExpr.getArrayOffset() and offsetExpr = arrayExpr.getArrayOffset() and
sink.asExpr() = offsetExpr and sink.asExpr() = offsetExpr and
not hasUpperBound(offsetExpr) not offsetIsAlwaysInBounds(arrayExpr, offsetExpr)
) )
} }
} }

View File

@@ -13,23 +13,85 @@
*/ */
import cpp import cpp
import semmle.code.cpp.controlflow.Guards
class WideCharPointerType extends PointerType { class WideCharPointerType extends PointerType {
WideCharPointerType() { this.getBaseType() instanceof WideCharType } WideCharPointerType() { this.getBaseType() instanceof WideCharType }
} }
/**
* Given type `t`, recurses through and returns all
* intermediate base types, including `t`.
*/
Type getABaseType(Type t) {
result = t
or
result = getABaseType(t.(DerivedType).getBaseType())
or
result = getABaseType(t.(TypedefType).getBaseType())
}
/** /**
* A type that may also be `CharPointerType`, but that are likely used as arbitrary buffers. * A type that may also be `CharPointerType`, but that are likely used as arbitrary buffers.
*/ */
class UnlikelyToBeAStringType extends Type { class UnlikelyToBeAStringType extends Type {
UnlikelyToBeAStringType() { UnlikelyToBeAStringType() {
this.(PointerType).getBaseType().(CharType).isUnsigned() or exists(Type targ | getABaseType(this) = targ |
this.(PointerType).getBaseType().getName().toLowerCase().matches("%byte") or // NOTE: not using CharType isUnsigned, but rather look for any explicitly declared unsigned
this.getName().toLowerCase().matches("%byte") or // char types. Assuming these are used for buffers, not strings.
this.(PointerType).getBaseType().hasName("uint8_t") targ.(CharType).getName().toLowerCase().matches("unsigned%") or
targ.getName().toLowerCase().matches(["uint8_t", "%byte%"])
)
} }
} }
// Types that can be wide depending on the UNICODE macro
// see https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
class UnicodeMacroDependentWidthType extends Type {
UnicodeMacroDependentWidthType() {
exists(Type targ | getABaseType(this) = targ |
targ.getName() in [
"LPCTSTR",
"LPTSTR",
"PCTSTR",
"PTSTR",
"TBYTE",
"TCHAR"
]
)
}
}
class UnicodeMacro extends Macro {
UnicodeMacro() { this.getName().toLowerCase().matches("%unicode%") }
}
class UnicodeMacroInvocation extends MacroInvocation {
UnicodeMacroInvocation() { this.getMacro() instanceof UnicodeMacro }
}
/**
* Holds when a expression whose type is UnicodeMacroDependentWidthType and
* is observed to be guarded by a check involving a bitwise-and operation
* with a UnicodeMacroInvocation.
* Such expressions are assumed to be checked dynamically, i.e.,
* the flag would indicate if UNICODE typing is set correctly to allow
* or disallow a widening cast.
*/
predicate isLikelyDynamicallyChecked(Expr e) {
e.getType() instanceof UnicodeMacroDependentWidthType and
exists(GuardCondition gc, BitwiseAndExpr bai, UnicodeMacroInvocation umi |
bai.getAnOperand() = umi.getExpr()
|
// bai == 0 is false when reaching `e.getBasicBlock()`.
// That is, bai != 0 when reaching `e.getBasicBlock()`.
gc.ensuresEq(bai, 0, e.getBasicBlock(), false)
or
// bai == k and k != 0 is true when reaching `e.getBasicBlock()`.
gc.ensuresEq(bai, any(int k | k != 0), e.getBasicBlock(), true)
)
}
from Expr e1, Cast e2 from Expr e1, Cast e2
where where
e2 = e1.getConversion() and e2 = e1.getConversion() and
@@ -42,7 +104,11 @@ where
not e1.getType() instanceof UnlikelyToBeAStringType and not e1.getType() instanceof UnlikelyToBeAStringType and
// Avoid castings from 'new' expressions as typically these will be safe // Avoid castings from 'new' expressions as typically these will be safe
// Example: `__Type* ret = reinterpret_cast<__Type*>(New(m_pmo) char[num * sizeof(__Type)]);` // Example: `__Type* ret = reinterpret_cast<__Type*>(New(m_pmo) char[num * sizeof(__Type)]);`
not exists(NewOrNewArrayExpr newExpr | newExpr.getAChild*() = e1) not exists(NewOrNewArrayExpr newExpr | newExpr.getAChild*() = e1) and
// Avoid cases where the cast is guarded by a check to determine if
// unicode encoding is enabled in such a way to disallow the dangerous cast
// at runtime.
not isLikelyDynamicallyChecked(e1)
select e1, select e1,
"Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() + "Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
". Use of invalid string can lead to undefined behavior." ". Use of invalid string can lead to undefined behavior."

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

@@ -49,7 +49,7 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
predicate functionImperfectlyExtracted(Function f) { predicate functionImperfectlyExtracted(Function f) {
exists(CompilerError e | f.getBlock().getLocation().subsumes(e.getLocation())) exists(CompilerError e | f.getBlock().getLocation().subsumes(e.getLocation()))
or or
exists(ErrorExpr ee | ee.getEnclosingFunction() = f) f.hasErrors()
or or
count(f.getType()) > 1 count(f.getType()) > 1
or or

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,14 +9,14 @@ void goodTest1(unsigned char *src){
unsigned char dst[50]; unsigned char dst[50];
_mbsnbcpy(dst,src,sizeof(dst)); // GOOD _mbsnbcpy(dst,src,sizeof(dst)); // GOOD
} }
size_t badTest1(unsigned char *src){ static size_t badTest1(unsigned char *src){
int cb = 0; int cb = 0;
unsigned char dst[50]; unsigned char dst[50];
while( cb < sizeof(dst) ) while( cb < sizeof(dst) )
dst[cb++]=*src++; // BAD dst[cb++]=*src++; // BAD
return _mbclen(dst); return _mbclen(dst);
} }
void goodTest2(unsigned char *src){ static void goodTest2(unsigned char *src){
int cb = 0; int cb = 0;
unsigned char dst[50]; unsigned char dst[50];
@@ -27,7 +27,7 @@ void goodTest2(unsigned char *src){
src=_mbsinc(src); src=_mbsinc(src);
} }
} }
void badTest2(unsigned char *src){ static void badTest2(unsigned char *src){
int cb = 0; int cb = 0;
unsigned char dst[50]; unsigned char dst[50];
@@ -38,11 +38,11 @@ void badTest2(unsigned char *src){
src=_mbsinc(src); src=_mbsinc(src);
} }
} }
void goodTest3(){ static void goodTest3(){
wchar_t name[50]; wchar_t name[50];
name[sizeof(name) / sizeof(*name) - 1] = L'\0'; // GOOD name[sizeof(name) / sizeof(*name) - 1] = L'\0'; // GOOD
} }
void badTest3(){ static void badTest3(){
wchar_t name[50]; wchar_t name[50];
name[sizeof(name) - 1] = L'\0'; // BAD 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; return q;
} }
void test1() { void flowout_test1() {
int x = 0; int x = 0;
int* p = &x; int* p = &x;
deref(&p)[0] = source(); deref(&p)[0] = source();
@@ -95,7 +95,7 @@ void addtaint2(int** p) { // $ ast-def=p ir-def=*p ir-def=**p
addtaint1(q); addtaint1(q);
} }
void test2() { void flowout_test2() {
int x = 0; int x = 0;
int* p = &x; int* p = &x;
addtaint2(&p); addtaint2(&p);

View File

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

View File

@@ -5,7 +5,7 @@ int source();
void sink(...); void sink(...);
bool random(); bool random();
void test1() { void on_entry_test1() {
int x = source(); int x = source();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
x = 0; x = 0;
@@ -13,7 +13,7 @@ void test1() {
sink(x); // $ SPURIOUS: ir sink(x); // $ SPURIOUS: ir
} }
void test2(int iterations) { void on_entry_test2(int iterations) {
int x = source(); int x = source();
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
x = 0; x = 0;
@@ -21,7 +21,7 @@ void test2(int iterations) {
sink(x); // $ ast,ir sink(x); // $ ast,ir
} }
void test3() { void on_entry_test3() {
int x = 0; int x = 0;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
x = source(); x = source();
@@ -29,7 +29,7 @@ void test3() {
sink(x); // $ ast,ir sink(x); // $ ast,ir
} }
void test4() { void on_entry_test4() {
int x = source(); int x = source();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
if (random()) if (random())
@@ -39,7 +39,7 @@ void test4() {
sink(x); // $ ast,ir sink(x); // $ ast,ir
} }
void test5() { void on_entry_test5() {
int x = source(); int x = source();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
if (random()) if (random())
@@ -49,7 +49,7 @@ void test5() {
sink(x); // $ ast,ir sink(x); // $ ast,ir
} }
void test6() { void on_entry_test6() {
int y; int y;
int x = source(); int x = source();
for (int i = 0; i < 10 && (y = 1); i++) { for (int i = 0; i < 10 && (y = 1); i++) {
@@ -57,7 +57,7 @@ void test6() {
sink(x); // $ ast,ir sink(x); // $ ast,ir
} }
void test7() { void on_entry_test7() {
int y; int y;
int x = source(); int x = source();
for (int i = 0; i < 10 && (y = 1); i++) { for (int i = 0; i < 10 && (y = 1); i++) {
@@ -66,7 +66,7 @@ void test7() {
sink(x); // $ SPURIOUS: ir sink(x); // $ SPURIOUS: ir
} }
void test8() { void on_entry_test8() {
int x = source(); int x = source();
// It appears to the analysis that the condition can exit after `i < 10` // 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 // without having assigned to `x`. That is an effect of how the
@@ -78,7 +78,7 @@ void test8() {
sink(x); // $ SPURIOUS: ast,ir sink(x); // $ SPURIOUS: ast,ir
} }
void test9() { void on_entry_test9() {
int y; int y;
int x = source(); int x = source();
for (int i = 0; (y = 1) && i < 10; i++) { for (int i = 0; (y = 1) && i < 10; i++) {
@@ -86,14 +86,14 @@ void test9() {
sink(x); // $ ast,ir sink(x); // $ ast,ir
} }
void test10() { void on_entry_test10() {
int x = source(); int x = source();
for (int i = 0; (x = 1) && i < 10; i++) { for (int i = 0; (x = 1) && i < 10; i++) {
} }
sink(x); // no flow sink(x); // no flow
} }
void test10(int b, int d) { void on_entry_test10(int b, int d) {
int i = 0; int i = 0;
int x = source(); int x = source();
if (b) 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: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: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: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:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | 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 | | | 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() { void test_TaintInheritingContent() {
TaintInheritingContentObject obj = source(true); TaintInheritingContentObject obj = source(true);
sink(obj.flowFromObject); // $ ir MISSING: ast 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 | | | | c.c | c.c | CFile, MetricFile | C | | |
| files1.cpp | library-tests/files/files1.cpp | CppFile, MetricFile | C++ | swap | t | | files1.cpp | files1.cpp | CppFile, MetricFile | C++ | swap | t |
| files1.h | library-tests/files/files1.h | HeaderFile, MetricFile | | swap | | | files1.h | files1.h | HeaderFile, MetricFile | | swap | |
| files2.cpp | library-tests/files/files2.cpp | CppFile, MetricFile | C++ | g | x, y | | files2.cpp | files2.cpp | CppFile, MetricFile | C++ | g | x, y |

View File

@@ -9055,6 +9055,8 @@ ir.cpp:
# 733| Value = [Literal] 7 # 733| Value = [Literal] 7
# 733| ValueCategory = prvalue # 733| ValueCategory = prvalue
# 735| getChild(1): [Handler] <handler> # 735| getChild(1): [Handler] <handler>
# 735| getParameter(): [Parameter] s
# 735| Type = [PointerType] const char *
# 735| getBlock(): [CatchBlock] { ... } # 735| getBlock(): [CatchBlock] { ... }
# 736| getStmt(0): [ExprStmt] ExprStmt # 736| getStmt(0): [ExprStmt] ExprStmt
# 736| getExpr(): [ThrowExpr] throw ... # 736| getExpr(): [ThrowExpr] throw ...
@@ -9067,6 +9069,8 @@ ir.cpp:
# 736| Type = [PointerType] const char * # 736| Type = [PointerType] const char *
# 736| ValueCategory = prvalue(load) # 736| ValueCategory = prvalue(load)
# 738| getChild(2): [Handler] <handler> # 738| getChild(2): [Handler] <handler>
# 738| getParameter(): [Parameter] e
# 738| Type = [LValueReferenceType] const String &
# 738| getBlock(): [CatchBlock] { ... } # 738| getBlock(): [CatchBlock] { ... }
# 740| getChild(3): [Handler] <handler> # 740| getChild(3): [Handler] <handler>
# 740| getBlock(): [CatchAnyBlock] { ... } # 740| getBlock(): [CatchAnyBlock] { ... }
@@ -12852,6 +12856,8 @@ ir.cpp:
# 1200| Value = [Literal] 7 # 1200| Value = [Literal] 7
# 1200| ValueCategory = prvalue # 1200| ValueCategory = prvalue
# 1202| getChild(1): [Handler] <handler> # 1202| getChild(1): [Handler] <handler>
# 1202| getParameter(): [Parameter] s
# 1202| Type = [PointerType] const char *
# 1202| getBlock(): [CatchBlock] { ... } # 1202| getBlock(): [CatchBlock] { ... }
# 1203| getStmt(0): [ExprStmt] ExprStmt # 1203| getStmt(0): [ExprStmt] ExprStmt
# 1203| getExpr(): [ThrowExpr] throw ... # 1203| getExpr(): [ThrowExpr] throw ...
@@ -12864,6 +12870,8 @@ ir.cpp:
# 1203| Type = [PointerType] const char * # 1203| Type = [PointerType] const char *
# 1203| ValueCategory = prvalue(load) # 1203| ValueCategory = prvalue(load)
# 1205| getChild(2): [Handler] <handler> # 1205| getChild(2): [Handler] <handler>
# 1205| getParameter(): [Parameter] e
# 1205| Type = [LValueReferenceType] const String &
# 1205| getBlock(): [CatchBlock] { ... } # 1205| getBlock(): [CatchBlock] { ... }
# 1207| getStmt(1): [ReturnStmt] return ... # 1207| getStmt(1): [ReturnStmt] return ...
# 1211| [TopLevelFunction] void VectorTypes(int) # 1211| [TopLevelFunction] void VectorTypes(int)
@@ -20586,6 +20594,8 @@ ir.cpp:
# 2281| Type = [Struct] String # 2281| Type = [Struct] String
# 2281| ValueCategory = lvalue # 2281| ValueCategory = lvalue
# 2282| getChild(1): [Handler] <handler> # 2282| getChild(1): [Handler] <handler>
# 2282| getParameter(): [Parameter] s
# 2282| Type = [PointerType] const char *
# 2282| getBlock(): [CatchBlock] { ... } # 2282| getBlock(): [CatchBlock] { ... }
# 2283| getStmt(0): [ExprStmt] ExprStmt # 2283| getStmt(0): [ExprStmt] ExprStmt
# 2283| getExpr(): [ThrowExpr] throw ... # 2283| getExpr(): [ThrowExpr] throw ...
@@ -20598,6 +20608,8 @@ ir.cpp:
# 2283| Type = [PointerType] const char * # 2283| Type = [PointerType] const char *
# 2283| ValueCategory = prvalue(load) # 2283| ValueCategory = prvalue(load)
# 2285| getChild(2): [Handler] <handler> # 2285| getChild(2): [Handler] <handler>
# 2285| getParameter(): [Parameter] e
# 2285| Type = [LValueReferenceType] const String &
# 2285| getBlock(): [CatchBlock] { ... } # 2285| getBlock(): [CatchBlock] { ... }
# 2287| getChild(3): [Handler] <handler> # 2287| getChild(3): [Handler] <handler>
# 2287| getBlock(): [CatchAnyBlock] { ... } # 2287| getBlock(): [CatchAnyBlock] { ... }
@@ -22845,6 +22857,8 @@ ir.cpp:
# 2537| Value = [Literal] 42 # 2537| Value = [Literal] 42
# 2537| ValueCategory = prvalue # 2537| ValueCategory = prvalue
# 2539| getChild(1): [Handler] <handler> # 2539| getChild(1): [Handler] <handler>
# 2539| getParameter(): [Parameter] (unnamed parameter 0)
# 2539| Type = [PlainCharType] char
# 2539| getBlock(): [CatchBlock] { ... } # 2539| getBlock(): [CatchBlock] { ... }
# 2541| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor # 2541| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
# 2541| Type = [VoidType] void # 2541| Type = [VoidType] void
@@ -23564,6 +23578,42 @@ ir.cpp:
# 2686| Value = [CStyleCast] 0 # 2686| Value = [CStyleCast] 0
# 2686| ValueCategory = prvalue # 2686| ValueCategory = prvalue
# 2687| getStmt(1): [ReturnStmt] return ... # 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
#-----| <params>:
# 2692| getRequirement(0): [GTExpr,SimpleRequirementExpr] ... > ...
# 2692| Type = [BoolType] bool
# 2692| ValueCategory = prvalue
# 2692| getGreaterOperand(): [SizeofTypeOperator] sizeof(int)
# 2692| Type = [LongType] unsigned long
# 2692| Value = [SizeofTypeOperator] 4
# 2692| ValueCategory = prvalue
# 2692| getLesserOperand(): [Literal] 0
# 2692| Type = [IntType] int
# 2692| Value = [Literal] 0
# 2692| ValueCategory = prvalue
# 2692| getLesserOperand().getFullyConverted(): [CStyleCast] (unsigned long)...
# 2692| Conversion = [IntegralConversion] integral conversion
# 2692| Type = [LongType] unsigned long
# 2692| 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: many-defs-per-use.cpp:
# 34| [TopLevelFunction] void many_defs_per_use() # 34| [TopLevelFunction] void many_defs_per_use()
# 34| <params>: # 34| <params>:

View File

@@ -19099,6 +19099,24 @@ ir.cpp:
# 2684| Block 8 # 2684| Block 8
# 2684| v2684_14(void) = Unreached : # 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: many-defs-per-use.cpp:
# 34| void many_defs_per_use() # 34| void many_defs_per_use()
# 34| Block 0 # 34| Block 0

View File

@@ -2686,4 +2686,13 @@ void test(bool b)
twice_call_use(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 // semmle-extractor-options: -std=c++20 --clang

View File

@@ -17422,6 +17422,23 @@ ir.cpp:
# 2684| v2684_7(void) = AliasedUse : ~m? # 2684| v2684_7(void) = AliasedUse : ~m?
# 2684| v2684_8(void) = ExitFunction : # 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: many-defs-per-use.cpp:
# 34| void many_defs_per_use() # 34| void many_defs_per_use()
# 34| Block 0 # 34| Block 0

View File

@@ -2,25 +2,168 @@
| file://:0:0:0:0 | (unnamed parameter 0) | false | | file://:0:0:0:0 | (unnamed parameter 0) | false |
| file://:0:0:0:0 | __super | false | | file://:0:0:0:0 | __super | false |
| file://:0:0:0:0 | __va_list_tag | false | | file://:0:0:0:0 | __va_list_tag | false |
| file://:0:0:0:0 | decltype([...](...){...}) | false |
| file://:0:0:0:0 | operator= | false | | file://:0:0:0:0 | operator= | false |
| file://:0:0:0:0 | operator= | false | | file://:0:0:0:0 | operator= | false |
| test.cpp:0:0:0:0 | test.cpp | false | | test.cpp:0:0:0:0 | test.cpp | false |
| test.cpp:2:1:2:61 | #define FOO class S{int i; void f(void) { int j; return; } }; | false | | test.cpp:2:1:2:68 | #define CLASS_DECL class S{int i; void f(void) { int j; return; } }; | false |
| test.cpp:4:1:4:1 | S | false | | test.cpp:4:1:4:1 | S | false |
| test.cpp:4:1:4:1 | declaration of S | false | | test.cpp:4:1:4:1 | declaration of S | false |
| test.cpp:4:1:4:1 | declaration of operator= | false | | test.cpp:4:1:4:1 | declaration of operator= | false |
| test.cpp:4:1:4:1 | declaration of operator= | false | | test.cpp:4:1:4:1 | declaration of operator= | false |
| test.cpp:4:1:4:1 | operator= | false | | test.cpp:4:1:4:1 | operator= | false |
| test.cpp:4:1:4:1 | operator= | false | | test.cpp:4:1:4:1 | operator= | false |
| test.cpp:4:1:4:3 | FOO | false | | test.cpp:4:1:4:10 | CLASS_DECL | false |
| test.cpp:4:1:4:3 | S | false | | test.cpp:4:1:4:10 | S | false |
| test.cpp:4:1:4:3 | declaration | true | | test.cpp:4:1:4:10 | declaration | true |
| test.cpp:4:1:4:3 | definition of S | true | | test.cpp:4:1:4:10 | definition of S | true |
| test.cpp:4:1:4:3 | definition of f | true | | test.cpp:4:1:4:10 | definition of f | true |
| test.cpp:4:1:4:3 | definition of i | true | | test.cpp:4:1:4:10 | definition of i | true |
| test.cpp:4:1:4:3 | definition of j | true | | test.cpp:4:1:4:10 | definition of j | true |
| test.cpp:4:1:4:3 | f | false | | test.cpp:4:1:4:10 | f | false |
| test.cpp:4:1:4:3 | i | false | | test.cpp:4:1:4:10 | i | false |
| test.cpp:4:1:4:3 | j | true | | test.cpp:4:1:4:10 | j | true |
| test.cpp:4:1:4:3 | return ... | true | | test.cpp:4:1:4:10 | return ... | true |
| test.cpp:4:1:4:3 | { ... } | true | | test.cpp:4:1:4:10 | { ... } | true |
| test.cpp:6:1:6:42 | #define FUNCTION_DECL void f1() { int k; } | false |
| test.cpp:8:1:8:13 | FUNCTION_DECL | false |
| test.cpp:8:1:8:13 | declaration | true |
| test.cpp:8:1:8:13 | definition of f1 | true |
| test.cpp:8:1:8:13 | definition of k | true |
| test.cpp:8:1:8:13 | f1 | false |
| test.cpp:8:1:8:13 | k | true |
| test.cpp:8:1:8:13 | return ... | true |
| test.cpp:8:1:8:13 | { ... } | true |
| test.cpp:10:1:10:33 | #define VARIABLE_DECL int v1 = 1; | false |
| test.cpp:12:1:12:13 | 1 | true |
| test.cpp:12:1:12:13 | VARIABLE_DECL | false |
| test.cpp:12:1:12:13 | definition of v1 | true |
| test.cpp:12:1:12:13 | initializer for v1 | true |
| test.cpp:12:1:12:13 | v1 | true |
| test.cpp:14:1:14:35 | #define TYPE_DECL_1 typedef int t1; | false |
| test.cpp:16:1:16:11 | TYPE_DECL_1 | false |
| test.cpp:16:1:16:11 | declaration of t1 | true |
| test.cpp:16:1:16:11 | t1 | false |
| test.cpp:18:1:18:35 | #define TYPE_DECL_2 using t2 = int; | false |
| test.cpp:20:1:20:11 | TYPE_DECL_2 | false |
| test.cpp:20:1:20:11 | declaration of t2 | true |
| test.cpp:20:1:20:11 | t2 | false |
| test.cpp:22:1:22:47 | #define NAMESPACE_DECL namespace ns { int v2; } | false |
| test.cpp:24:1:24:14 | NAMESPACE_DECL | false |
| test.cpp:24:1:24:14 | definition of v2 | true |
| test.cpp:24:1:24:14 | ns | false |
| test.cpp:24:1:24:14 | ns | false |
| test.cpp:24:1:24:14 | v2 | true |
| test.cpp:26:1:26:43 | #define USING_NAMESPACE using namespace ns; | false |
| test.cpp:28:1:28:34 | #define ENUM_CONSTANT enum_element | false |
| test.cpp:30:12:30:21 | definition of enum_class | false |
| test.cpp:30:12:30:21 | enum_class | false |
| test.cpp:30:25:30:37 | ENUM_CONSTANT | false |
| test.cpp:30:25:30:37 | enum_element | false |
| test.cpp:32:1:32:41 | #define USING_ENUM using enum enum_class; | false |
| test.cpp:34:1:34:10 | USING_ENUM | false |
| test.cpp:34:1:34:10 | using enum enum_class | false |
| test.cpp:36:1:36:48 | #define STATIC_ASSERT static_assert(1 == 1, ""); | false |
| test.cpp:38:1:38:13 | 1 | true |
| test.cpp:38:1:38:13 | 1 | true |
| test.cpp:38:1:38:13 | ... == ... | true |
| test.cpp:38:1:38:13 | STATIC_ASSERT | false |
| test.cpp:38:1:38:13 | static_assert(..., "") | false |
| test.cpp:40:1:40:42 | #define ATTRIBUTE [[nodiscard("reason1")]] | false |
| test.cpp:42:1:42:9 | ATTRIBUTE | false |
| test.cpp:42:1:42:9 | nodiscard | false |
| test.cpp:42:1:42:9 | reason1 | false |
| test.cpp:42:1:42:9 | reason1 | true |
| test.cpp:43:5:43:6 | declaration of f2 | false |
| test.cpp:43:5:43:6 | f2 | false |
| test.cpp:45:1:45:31 | #define ATTRIBUTE_ARG "reason2" | false |
| test.cpp:47:3:47:11 | nodiscard | false |
| test.cpp:47:13:47:25 | ATTRIBUTE_ARG | false |
| test.cpp:47:13:47:25 | reason2 | false |
| test.cpp:47:13:47:25 | reason2 | true |
| test.cpp:48:5:48:6 | declaration of f3 | false |
| test.cpp:48:5:48:6 | f3 | false |
| test.cpp:50:1:50:16 | #define TYPE int | false |
| test.cpp:52:1:52:4 | TYPE | false |
| test.cpp:52:6:52:7 | definition of v3 | true |
| test.cpp:52:6:52:7 | v3 | true |
| test.cpp:52:11:52:11 | 1 | false |
| test.cpp:52:11:52:11 | initializer for v3 | false |
| test.cpp:54:1:54:29 | #define DERIVATION : public S | false |
| test.cpp:56:7:56:7 | T | false |
| test.cpp:56:7:56:7 | T | false |
| test.cpp:56:7:56:7 | declaration of T | false |
| test.cpp:56:7:56:7 | declaration of operator= | false |
| test.cpp:56:7:56:7 | declaration of operator= | false |
| test.cpp:56:7:56:7 | definition of T | false |
| test.cpp:56:7:56:7 | operator= | false |
| test.cpp:56:7:56:7 | operator= | false |
| test.cpp:56:9:56:18 | DERIVATION | false |
| test.cpp:56:9:56:18 | derivation | false |
| test.cpp:58:1:58:31 | #define FRIEND friend int f3(); | false |
| test.cpp:60:7:60:7 | U | false |
| test.cpp:60:7:60:7 | declaration of operator= | false |
| test.cpp:60:7:60:7 | declaration of operator= | false |
| test.cpp:60:7:60:7 | definition of U | false |
| test.cpp:60:7:60:7 | operator= | false |
| test.cpp:60:7:60:7 | operator= | false |
| test.cpp:61:3:61:8 | FRIEND | false |
| test.cpp:61:3:61:8 | U's friend | false |
| test.cpp:64:1:64:24 | #define NAME_QUAL_1 ns:: | false |
| test.cpp:66:1:66:22 | #define NAME_QUAL_2 ns | false |
| test.cpp:68:1:68:19 | #define LOCAL_VAR m | false |
| test.cpp:70:6:70:7 | definition of f4 | false |
| test.cpp:70:6:70:7 | f4 | false |
| test.cpp:70:11:76:1 | { ... } | false |
| test.cpp:71:5:71:8 | ns:: | false |
| test.cpp:71:5:71:15 | NAME_QUAL_1 | false |
| test.cpp:71:5:71:18 | v2 | false |
| test.cpp:71:5:71:19 | ExprStmt | false |
| test.cpp:72:5:72:8 | ns:: | false |
| test.cpp:72:5:72:15 | NAME_QUAL_2 | false |
| test.cpp:72:5:72:21 | v2 | false |
| test.cpp:72:5:72:22 | ExprStmt | false |
| test.cpp:73:5:73:23 | declaration | false |
| test.cpp:73:9:73:17 | LOCAL_VAR | false |
| test.cpp:73:9:73:17 | definition of m | true |
| test.cpp:73:9:73:17 | m | true |
| test.cpp:73:20:73:22 | 42 | false |
| test.cpp:73:20:73:22 | initializer for m | false |
| test.cpp:74:5:74:41 | declaration | false |
| test.cpp:74:10:74:10 | definition of l | false |
| test.cpp:74:10:74:10 | l | false |
| test.cpp:74:13:74:40 | [...](...){...} | false |
| test.cpp:74:13:74:40 | initializer for l | false |
| test.cpp:74:13:74:40 | {...} | false |
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
| test.cpp:74:14:74:14 | declaration of (unnamed constructor) | false |
| test.cpp:74:14:74:14 | declaration of (unnamed constructor) | false |
| test.cpp:74:14:74:14 | definition of (unnamed constructor) | false |
| test.cpp:74:14:74:14 | definition of operator= | false |
| test.cpp:74:14:74:14 | operator= | false |
| test.cpp:74:15:74:15 | definition of m | false |
| test.cpp:74:15:74:15 | m | false |
| test.cpp:74:15:74:15 | m | false |
| test.cpp:74:15:74:23 | LOCAL_VAR | false |
| test.cpp:74:15:74:23 | m | true |
| test.cpp:74:25:74:25 | definition of operator() | false |
| test.cpp:74:25:74:25 | operator() | false |
| test.cpp:74:28:74:40 | { ... } | false |
| test.cpp:74:30:74:38 | return ... | false |
| test.cpp:74:37:74:37 | (int)... | false |
| test.cpp:75:5:75:5 | (const lambda [] type at line 74, col. 14)... | false |
| test.cpp:75:5:75:5 | l | false |
| test.cpp:75:5:75:8 | ExprStmt | false |
| test.cpp:75:6:75:6 | call to operator() | false |
| test.cpp:76:1:76:1 | return ... | false |
| test.cpp:78:1:78:15 | #define ID(x) x | false |
| test.cpp:79:1:79:23 | #define NESTED(x) ID(x) | false |
| test.cpp:80:5:80:6 | definition of v4 | false |
| test.cpp:80:5:80:6 | v4 | false |
| test.cpp:80:10:80:18 | ID(x) | false |
| test.cpp:80:10:80:18 | NESTED(x) | false |
| test.cpp:80:17:80:17 | 1 | true |
| test.cpp:80:17:80:17 | initializer for v4 | true |
| test.cpp:82:1:82:39 | // semmle-extractor-options: -std=c++20 | false |

View File

@@ -1,5 +1,82 @@
#define FOO class S{int i; void f(void) { int j; return; } }; #define CLASS_DECL class S{int i; void f(void) { int j; return; } };
FOO CLASS_DECL
#define FUNCTION_DECL void f1() { int k; }
FUNCTION_DECL
#define VARIABLE_DECL int v1 = 1;
VARIABLE_DECL
#define TYPE_DECL_1 typedef int t1;
TYPE_DECL_1
#define TYPE_DECL_2 using t2 = int;
TYPE_DECL_2
#define NAMESPACE_DECL namespace ns { int v2; }
NAMESPACE_DECL
#define USING_NAMESPACE using namespace ns;
#define ENUM_CONSTANT enum_element
enum class enum_class { ENUM_CONSTANT };
#define USING_ENUM using enum enum_class;
USING_ENUM
#define STATIC_ASSERT static_assert(1 == 1, "");
STATIC_ASSERT
#define ATTRIBUTE [[nodiscard("reason1")]]
ATTRIBUTE
int f2();
#define ATTRIBUTE_ARG "reason2"
[[nodiscard(ATTRIBUTE_ARG)]]
int f3();
#define TYPE int
TYPE v3 = 1;
#define DERIVATION : public S
class T DERIVATION {};
#define FRIEND friend int f3();
class U {
FRIEND
};
#define NAME_QUAL_1 ns::
#define NAME_QUAL_2 ns
#define LOCAL_VAR m
void f4() {
NAME_QUAL_1 v2;
NAME_QUAL_2 :: v2;
int LOCAL_VAR = 42;
auto l = [LOCAL_VAR]() { return m; };
l();
}
#define ID(x) x
#define NESTED(x) ID(x)
int v4 = NESTED(1);
// semmle-extractor-options: -std=c++20

View File

@@ -1,6 +1,6 @@
| containserror.cpp:0:0:0:0 | containserror.cpp | query-tests/Diagnostics/containserror.cpp | fromSource, normalTermination | | containserror.cpp:0:0:0:0 | containserror.cpp | containserror.cpp | fromSource, normalTermination |
| containswarning.cpp:0:0:0:0 | containswarning.cpp | query-tests/Diagnostics/containswarning.cpp | fromSource, normalTermination | | containswarning.cpp:0:0:0:0 | containswarning.cpp | containswarning.cpp | fromSource, normalTermination |
| doesnotcompile.cpp:0:0:0:0 | doesnotcompile.cpp | query-tests/Diagnostics/doesnotcompile.cpp | ExtractionProblem (severity 1), fromSource, normalTermination | | doesnotcompile.cpp:0:0:0:0 | doesnotcompile.cpp | doesnotcompile.cpp | ExtractionProblem (severity 1), fromSource, normalTermination |
| file://:0:0:0:0 | | | | | file://:0:0:0:0 | | | |
| header.h:0:0:0:0 | header.h | query-tests/Diagnostics/header.h | fromSource | | header.h:0:0:0:0 | header.h | header.h | fromSource |
| successful.cpp:0:0:0:0 | successful.cpp | query-tests/Diagnostics/successful.cpp | fromSource, normalTermination | | 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_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 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.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 | 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_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 | 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_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 | 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_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 | 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_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 | 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_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 | 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_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 | 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_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 | 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_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 | 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_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 | 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_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 | query-tests/Documentation/DocumentApi/user1.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 | query-tests/Documentation/DocumentApi/user2.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 | query-tests/Documentation/DocumentApi/user1.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 | query-tests/Documentation/DocumentApi/user2.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 | | /main.cpp<\|>LibC<\|>unknown | 5 |
| /query-tests/Metrics/Dependencies/include.h<\|>LibD<\|>unknown | 1 | | /include.h<\|>LibD<\|>unknown | 1 |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibA<\|>unknown | 1 | | /main.cpp<\|>LibA<\|>unknown | 1 |
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibB<\|>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 | | /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 | | /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 | | /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 | | /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: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: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: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: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:9:9:9:9 | i | test1.c:18:16:18:16 | i | provenance | |
| test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i | provenance | | | test1.c:11:9:11:9 | i | test1.c:34:16:34:16 | i | provenance | |
| test1.c:13:9:13:9 | i | test1.c:48:16:48:16 | i | provenance | | | test1.c:12:9:12:9 | i | test1.c:42:16:42:16 | i | provenance | |
| test1.c:16:16:16:16 | i | test1.c:18:16:18:16 | i | provenance | | | test1.c:13:9:13:9 | i | test1.c:50:16:50:16 | i | provenance | |
| test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i | provenance | | | test1.c:18:16:18:16 | i | test1.c:20:16:20:16 | i | provenance | |
| test1.c:48:16:48:16 | i | test1.c:51:3:51:7 | ... = ... | provenance | | | test1.c:34:16:34:16 | i | test1.c:35:11:35:11 | i | provenance | |
| test1.c:51:3:51:7 | ... = ... | test1.c:53:15:53:15 | j | 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 nodes
| test1.c:7:26:7:29 | **argv | semmle.label | **argv | | 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:8:11:8:14 | call to atoi | semmle.label | call to atoi |
| test1.c:9:9:9:9 | i | semmle.label | i | | test1.c:9:9:9:9 | i | semmle.label | i |
| test1.c:11:9:11: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: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:18:16:18:16 | i | semmle.label | i |
| test1.c:32:16:32:16 | i | semmle.label | i | | test1.c:20:16:20:16 | i | semmle.label | i |
| test1.c:33:11:33:11 | i | semmle.label | i | | test1.c:34:16:34:16 | i | semmle.label | i |
| test1.c:48:16:48:16 | i | semmle.label | i | | test1.c:35:11:35:11 | i | semmle.label | i |
| test1.c:51:3:51:7 | ... = ... | semmle.label | ... = ... | | test1.c:42:16:42:16 | i | semmle.label | i |
| test1.c:53:15:53:15 | j | semmle.label | j | | 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 subpaths
#select #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: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: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: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: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: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); test3(i);
test4(i); test4(i);
test5(i); test5(i);
test6(i);
test7(argv[1]);
} }
void test1(int i) { void test1(int i) {
@@ -38,7 +40,7 @@ void test3(int i) {
} }
void test4(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; if ((i < 0) || (i >= 10)) return;
@@ -52,3 +54,26 @@ void test5(int i) {
j = myArray[j]; // BAD: j has not been validated 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 ///// //// Test code /////
void bad0(char *str) { static void bad0(char *str) {
// BAD -- Not allocating space for '\0' terminator // BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(strlen(str)); char *buffer = malloc(strlen(str));
strcpy(buffer, str); strcpy(buffer, str);
free(buffer); free(buffer);
} }
void good0(char *str) { static void good0(char *str) {
// GOOD -- Allocating extra byte for terminator // GOOD -- Allocating extra byte for terminator
char *buffer = malloc(strlen(str)+1); char *buffer = malloc(strlen(str)+1);
strcpy(buffer, str); strcpy(buffer, str);
@@ -26,7 +26,7 @@ void good0(char *str) {
} }
void bad1(char *str) { static void bad1(char *str) {
int len = strlen(str); int len = strlen(str);
// BAD -- Not allocating space for '\0' terminator // BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(len); char *buffer = malloc(len);
@@ -34,7 +34,7 @@ void bad1(char *str) {
free(buffer); free(buffer);
} }
void good1(char *str) { static void good1(char *str) {
int len = strlen(str); int len = strlen(str);
// GOOD -- Allocating extra byte for terminator // GOOD -- Allocating extra byte for terminator
char *buffer = malloc(len+1); 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); int len = strlen(str);
// BAD -- Not allocating space for '\0' terminator // BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(len); char *buffer = malloc(len);
@@ -51,7 +51,7 @@ void bad2(char *str) {
free(buffer); free(buffer);
} }
void good2(char *str) { static void good2(char *str) {
int len = strlen(str)+1; int len = strlen(str)+1;
// GOOD -- Allocating extra byte for terminator // GOOD -- Allocating extra byte for terminator
char *buffer = malloc(len); char *buffer = malloc(len);
@@ -59,14 +59,14 @@ void good2(char *str) {
free(buffer); free(buffer);
} }
void bad3(char *str) { static void bad3(char *str) {
// BAD -- Not allocating space for '\0' terminator // BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(strlen(str) * sizeof(char)); char *buffer = malloc(strlen(str) * sizeof(char));
strcpy(buffer, str); strcpy(buffer, str);
free(buffer); free(buffer);
} }
void good3(char *str) { static void good3(char *str) {
// GOOD -- Allocating extra byte for terminator // GOOD -- Allocating extra byte for terminator
char *buffer = malloc((strlen(str) + 1) * sizeof(char)); char *buffer = malloc((strlen(str) + 1) * sizeof(char));
strcpy(buffer, str); strcpy(buffer, str);
@@ -75,7 +75,7 @@ void good3(char *str) {
void *memcpy(void *s1, const void *s2, size_t n); 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 // GOOD -- allocating a non zero-terminated string
int len = strlen(str); int len = strlen(str);
char *buffer = malloc(len); char *buffer = malloc(len);

View File

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

View File

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

View File

@@ -1,4 +1,6 @@
edges 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: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: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 | | | 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:3:39:18 | ... = ... | provenance | |
| test2.cpp:38:13:38:16 | call to atoi | test2.cpp:39:9:39:11 | num | 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 | | | 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: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: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: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: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: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 | | | 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:28:10:31 | **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:28:10:31 | **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: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: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:10 | len2 | provenance | |
| test.c:41:5:41:24 | ... = ... | test.c:44:7:44:12 | ... -- | 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: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 | | | test.c:54:7:54:12 | ... -- | test.c:54:7:54:10 | len3 | provenance | |
nodes 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:12:21:12:21 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | 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 | | 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:3:39:18 | ... = ... | semmle.label | ... = ... |
| test2.cpp:39:9:39:11 | num | semmle.label | num | | test2.cpp:39:9:39:11 | num | semmle.label | num |
| test2.cpp:40:3:40:5 | 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:5:5:5:17 | *getTaintedInt | semmle.label | *getTaintedInt |
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument | | 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 | | 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:2:18:20 | ... = ... | semmle.label | ... = ... |
| test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt | | test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:19:6:19:6 | y | semmle.label | y | | 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:11:24:11:27 | call to atoi | semmle.label | call to atoi |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections | | test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:41:5:41:24 | ... = ... | semmle.label | ... = ... | | 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: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 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 | | 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 | 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 | 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 | 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: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: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: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: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 |
| 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 |

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: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: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 | | 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. | main.cpp:7:27:7: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. | main.cpp:7:27:7: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 | | 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 |
| 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 |
| 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: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: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 | | 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: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: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 | | 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. | main.cpp:7:27:7: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. | main.cpp:7:27:7: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:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | main.cpp:7:27:7: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 |

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; typedef unsigned long size_t;
size_t strlen(const char *s); size_t strlen(const char *s);
int main(int argc, char** argv) { int main1(int argc, char** argv) {
int maxConnections = atoi(argv[1]); int maxConnections = atoi(argv[1]);
// BAD: arithmetic on a user input without any validation // BAD: arithmetic on a user input without any validation

View File

@@ -7,7 +7,7 @@
// Regression test for ODASA-6054: IntegerOverflowTainted should // Regression test for ODASA-6054: IntegerOverflowTainted should
// not report a result if the overflow happens in a macro expansion // not report a result if the overflow happens in a macro expansion
// from a macro that is defined in a system header. // 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]; char *cmd = argv[0];
int x = (int)(unsigned char)*cmd; // BAD: overflow int x = (int)(unsigned char)*cmd; // BAD: overflow
int y = CAST(*cmd); // BAD: overflow in macro expansion (macro is not from a system header) 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, // by comparing the value to 0. This means that the cast cannot overflow,
// regardless of what the input type is. // regardless of what the input type is.
int main(int argc, char **argv) { int main4(int argc, char **argv) {
char *p = argv[0]; char *p = argv[0];
if (!p[0]) { // GOOD: cast to bool. if (!p[0]) { // GOOD: cast to bool.
return 1; return 1;

View File

@@ -1,5 +1,6 @@
edges edges
nodes nodes
| errors.cpp:13:7:13:7 | definition of x | semmle.label | definition of x |
| test.cpp:11:6:11:8 | definition of foo | semmle.label | definition of foo | | test.cpp:11:6:11:8 | definition of foo | semmle.label | definition of foo |
| test.cpp:111:6:111:8 | definition of foo | semmle.label | definition of foo | | test.cpp:111:6:111:8 | definition of foo | semmle.label | definition of foo |
| test.cpp:226:7:226:7 | definition of x | semmle.label | definition of x | | test.cpp:226:7:226:7 | definition of x | semmle.label | definition of x |
@@ -14,6 +15,7 @@ nodes
| test.cpp:472:6:472:6 | definition of x | semmle.label | definition of x | | test.cpp:472:6:472:6 | definition of x | semmle.label | definition of x |
| test.cpp:479:6:479:6 | definition of x | semmle.label | definition of x | | test.cpp:479:6:479:6 | definition of x | semmle.label | definition of x |
#select #select
| errors.cpp:14:18:14:18 | x | errors.cpp:13:7:13:7 | definition of x | errors.cpp:13:7:13:7 | definition of x | The variable $@ may not be initialized at this access. | errors.cpp:13:7:13:7 | x | x |
| test.cpp:12:6:12:8 | foo | test.cpp:11:6:11:8 | definition of foo | test.cpp:11:6:11:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo | | test.cpp:12:6:12:8 | foo | test.cpp:11:6:11:8 | definition of foo | test.cpp:11:6:11:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo |
| test.cpp:113:6:113:8 | foo | test.cpp:111:6:111:8 | definition of foo | test.cpp:111:6:111:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo | | test.cpp:113:6:113:8 | foo | test.cpp:111:6:111:8 | definition of foo | test.cpp:111:6:111:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo |
| test.cpp:227:3:227:3 | x | test.cpp:226:7:226:7 | definition of x | test.cpp:226:7:226:7 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:226:7:226:7 | x | x | | test.cpp:227:3:227:3 | x | test.cpp:226:7:226:7 | definition of x | test.cpp:226:7:226:7 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:226:7:226:7 | x | x |

View File

@@ -0,0 +1,15 @@
// semmle-extractor-options: --expect_errors
int f1() {
int x;
initialize(&x); // error expression - initialize() is not defined
return x; // GOOD - assume x is initialized
}
void * operator new(unsigned long, bool);
void operator delete(void*, bool);
int f2() {
int x;
new(true) int (x); // BAD, ignore implicit error expression
}

View File

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

View File

@@ -53,4 +53,59 @@ void NonStringFalsePositiveTest2(unsigned char* buffer)
{ {
wchar_t *lpWchar = NULL; wchar_t *lpWchar = NULL;
lpWchar = (LPWSTR)buffer; // Possible False Positive lpWchar = (LPWSTR)buffer; // Possible False Positive
} }
typedef unsigned char BYTE;
using FOO = BYTE*;
void NonStringFalsePositiveTest3(FOO buffer)
{
wchar_t *lpWchar = NULL;
lpWchar = (LPWSTR)buffer; // GOOD
}
#define UNICODE 0x8
// assume EMPTY_MACRO is tied to if UNICODE is enabled
#ifdef EMPTY_MACRO
typedef WCHAR* LPTSTR;
#else
typedef char* LPTSTR;
#endif
void CheckedConversionFalsePositiveTest3(unsigned short flags, LPTSTR buffer)
{
wchar_t *lpWchar = NULL;
if(flags & UNICODE)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) == 0x8)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) != 0x8)
lpWchar = (LPWSTR)buffer; // BUG
else
lpWchar = (LPWSTR)buffer; // GOOD
// Bad operator precedence
if(flags & UNICODE == 0x8)
lpWchar = (LPWSTR)buffer; // BUG
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) != 0)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) == 0)
lpWchar = (LPWSTR)buffer; // BUG
else
lpWchar = (LPWSTR)buffer; // GOOD
lpWchar = (LPWSTR)buffer; // BUG
}

View File

@@ -3,3 +3,11 @@
| WcharCharConversion.cpp:24:22:24:27 | lpChar | Conversion from char * to wchar_t *. Use of invalid string can lead to undefined behavior. | | WcharCharConversion.cpp:24:22:24:27 | lpChar | Conversion from char * to wchar_t *. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:26:23:26:28 | lpChar | Conversion from char * to LPCWSTR. Use of invalid string can lead to undefined behavior. | | WcharCharConversion.cpp:26:23:26:28 | lpChar | Conversion from char * to LPCWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:27:17:27:22 | lpChar | Conversion from char * to LPWSTR. Use of invalid string can lead to undefined behavior. | | WcharCharConversion.cpp:27:17:27:22 | lpChar | Conversion from char * to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:82:21:82:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:87:21:87:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:90:21:90:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:96:21:96:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:98:21:98:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:103:21:103:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:106:21:106:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:110:20:110:25 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |

View File

@@ -1,3 +1,7 @@
## 1.7.27
No user-facing changes.
## 1.7.26 ## 1.7.26
No user-facing changes. 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 name: codeql/csharp-solorigate-all
version: 1.7.26 version: 1.7.28-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,3 +1,7 @@
## 1.7.27
No user-facing changes.
## 1.7.26 ## 1.7.26
No user-facing changes. 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 name: codeql/csharp-solorigate-queries
version: 1.7.26 version: 1.7.28-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,3 +1,7 @@
## 3.0.1
No user-facing changes.
## 3.0.0 ## 3.0.0
### Breaking Changes ### 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 name: codeql/csharp-all
version: 3.0.0 version: 3.0.2-dev
groups: csharp groups: csharp
dbscheme: semmlecode.csharp.dbscheme dbscheme: semmlecode.csharp.dbscheme
extractor: csharp 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 module CfgInput implements CfgShared::InputSig<Location> {
private import ControlFlowGraphImpl as Impl private import ControlFlowGraphImpl as Impl
private import Completion as Comp private import Completion as Comp
private import Splitting as Splitting
private import SuccessorType as ST private import SuccessorType as ST
private import semmle.code.csharp.Caching private import semmle.code.csharp.Caching
@@ -80,10 +79,6 @@ private module CfgInput implements CfgShared::InputSig<Location> {
Impl::scopeLast(scope, last, c) Impl::scopeLast(scope, last, c)
} }
class SplitKindBase = Splitting::TSplitKind;
class Split = Splitting::Split;
class SuccessorType = ST::SuccessorType; class SuccessorType = ST::SuccessorType;
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } 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. * A compilation.

View File

@@ -5,7 +5,8 @@
*/ */
import csharp import csharp
private import Completion private import Completion as Comp
private import Comp
private import ControlFlowGraphImpl private import ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg
private import semmle.code.csharp.controlflow.internal.PreSsa private import semmle.code.csharp.controlflow.internal.PreSsa
@@ -260,10 +261,12 @@ module ConditionalCompletionSplitting {
ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) } ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }
ConditionalCompletion getCompletion() { result = completion }
override string toString() { result = completion.toString() } 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 int getListOrder() { result = InitializerSplitting::getNextListOrder() }
override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) } override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) }
@@ -271,89 +274,64 @@ module ConditionalCompletionSplitting {
override string toString() { result = "ConditionalCompletion" } 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 class ConditionalCompletion = Comp::ConditionalCompletion;
{
ConditionalCompletion completion;
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) { bindingset[parent, parentCompletion]
succ(pred, succ, c) and predicate condPropagateExpr(
last(succ, _, completion) and 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 child = parent.(LogicalAndExpr).getAnOperand()
completion.(BooleanCompletion).getDual() = c
or or
last(succ.(LogicalAndExpr).getAnOperand(), pred, c) and child = parent.(LogicalOrExpr).getAnOperand()
completion = c
or or
last(succ.(LogicalOrExpr).getAnOperand(), pred, c) and parent = any(ConditionalExpr ce | child = [ce.getThen(), ce.getElse()])
completion = c
or or
succ = child = parent.(SwitchExpr).getACase()
any(ConditionalExpr ce |
last([ce.getThen(), ce.getElse()], pred, c) and
completion = c
)
or or
succ = child = parent.(SwitchCaseExpr).getBody()
or
parent =
any(NullCoalescingExpr nce | any(NullCoalescingExpr nce |
exists(Expr operand | if childCompletion instanceof NullnessCompletion
last(operand, pred, c) and then child = nce.getRightOperand()
completion = c else child = nce.getAnOperand()
|
if c instanceof NullnessCompletion
then operand = nce.getRightOperand()
else operand = 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 or
last(succ.(SwitchExpr).getACase(), pred, c) and child = parent.(OrPatternExpr).getAnOperand()
completion = c
or or
last(succ.(SwitchCaseExpr).getBody(), pred, c) and child = parent.(RecursivePatternExpr).getAChildExpr()
completion = c
or or
last(succ.(NotPatternExpr).getPattern(), pred, c) and child = parent.(PropertyPatternExpr).getPattern(_)
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
) )
} }
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 { module AssertionSplitting {

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