Compare commits

..

397 Commits

Author SHA1 Message Date
Michael B. Gale
12bc9f84bd Go: Remove extra "v"s in Autobuilder 2024-05-08 16:06:53 +01:00
Michael B. Gale
f64e617da2 Go: Make RequiredGoVersion resilient to different version formats and add tests 2024-05-08 16:06:53 +01:00
Michael B. Gale
97b95337b6 Go: Make toolchain functions resilient to different version formats 2024-05-08 16:06:53 +01:00
Michael B. Gale
a8d87ea4ea Go: Make getVersionToInstall resilient to different version strings 2024-05-08 16:06:53 +01:00
Michael B. Gale
dfa23197c7 Go: Add UnformatSemVer function 2024-05-08 16:06:53 +01:00
Michael B. Gale
8a9fd8c619 Go: Add FormatSemVer function 2024-05-08 16:06:52 +01:00
Michael B. Gale
42ee9afc69 Go: Improve documentation for GoVersionInfo 2024-05-08 14:29:40 +01:00
Michael B. Gale
c6809c46f5 Go: Improve documentation for GoVersionToSemVer and ToolchainVersionToSemVer 2024-05-08 14:27:05 +01:00
Michael B. Gale
0174a16d5a Go: Add tests for RequiredGoVersion 2024-05-08 13:09:25 +01:00
Michael B. Gale
69bf334a33 Go: Use GoVersionToSemVer 2024-05-08 13:09:25 +01:00
Michael B. Gale
01597ec23b Go: Add GoVersionToSemVer 2024-05-08 13:09:25 +01:00
Michael B. Gale
c9d1aa6354 Go: Use Toolchain directives in go.mod files, if available 2024-05-08 13:09:24 +01:00
Michael B. Gale
4666ed9957 Go: Add constructors for GoVersionInfo 2024-05-08 13:09:24 +01:00
Michael B. Gale
4e701a12db Go: Refactor go.mod version retrieval into its own method 2024-05-08 13:08:14 +01:00
Michael B. Gale
628064118f Go: Use Toolchain directives in go.work files, if available 2024-05-08 13:06:30 +01:00
Michael B. Gale
648b28c1d2 Go: Add ToolchainVersionToSemVer with tests 2024-05-08 13:06:20 +01:00
Jeroen Ketema
7b89c6c7f7 Merge pull request #16450 from jketema/inconsistent
C++: Add IR tests demonstrating some inconsistencies that may occur
2024-05-08 13:32:01 +02:00
Jeroen Ketema
9bc04e7591 Merge pull request #16447 from jketema/destructors-loc
C++: Update test results after extractor changes
2024-05-08 13:03:46 +02:00
Michael Nebel
c5403f4249 Merge pull request #16431 from michaelnebel/java/madinlinetest
Java: Models as Data inline like test.
2024-05-08 12:59:41 +02:00
Geoffrey White
871fd9aba3 Merge pull request #16405 from geoffw0/qhelp3
C++: Improve qhelp for StrncpyFlippedArgs.
2024-05-08 11:23:41 +01:00
Geoffrey White
880d56c576 Merge pull request #16404 from geoffw0/qhelp2
C++: Improve qhelp for WrongTypeFormatArguments.
2024-05-08 11:22:57 +01:00
Geoffrey White
9c8945f626 Merge pull request #16403 from geoffw0/qhelp1
C++: Improve qhelp for IncorrectNotOperatorUsage.
2024-05-08 11:22:15 +01:00
Jeroen Ketema
6575927630 C++: Add IR tests demonstrating some inconsistencies that may occur 2024-05-08 11:43:58 +02:00
Jeroen Ketema
2dcb55cc42 C++: Add bool operator to IR test 2024-05-08 11:38:50 +02:00
Owen Mansel-Chan
0338ffd125 Merge pull request #16444 from owen-mc/shared/update-summary-through-step-value
Shared data flow: Make summaryThroughStepValue include param outputs
2024-05-08 09:53:30 +01:00
Jeroen Ketema
61580da14d C++: Update test results after extractor changes 2024-05-08 08:43:20 +02:00
Erik Krogh Kristensen
8b91914826 Merge pull request #16417 from erik-krogh/dummyPass
JS: Remove some FPs from the hardcoded-credentials query
2024-05-07 18:00:58 +02:00
Owen Mansel-Chan
aab43afd81 Swift: accept test changes 2024-05-07 15:36:48 +01:00
Mathias Vorreiter Pedersen
99940a6084 Merge pull request #16440 from MathiasVP/fix-iterator-to-expired-container-fp-2
C++: Fix location of SSA def for local variable addresses
2024-05-07 14:39:13 +01:00
Owen Mansel-Chan
c11fac81fd Make summaryThroughStepValue include param outputs
This matches summaryThroughStepTaint.
2024-05-07 13:55:42 +01:00
Mathias Vorreiter Pedersen
85e71c30dc Merge pull request #16442 from MathiasVP/add-uninitialized-local-fp
C++: Add `cpp/uninitialized-local` FP
2024-05-07 13:35:02 +01:00
Mathias Vorreiter Pedersen
8e95395382 C++: Accept more test changes. 2024-05-07 12:55:42 +01:00
Mathias Vorreiter Pedersen
61fb89721a C++: Add 'cpp/uninitialized-local' FP. 2024-05-07 12:19:06 +01:00
Jeroen Ketema
8198b1a6ef Merge pull request #16426 from jketema/destructors-ranged-based-cleanup
C++: Update test results after extractor changes
2024-05-07 13:11:00 +02:00
Paolo Tranquilli
ab3d21ce7e Merge pull request #16441 from github/redsun82/lfs
Bazel: make `git_lfs_probe.py` compatible with python 3.8
2024-05-07 13:04:43 +02:00
Paolo Tranquilli
9f27eb3eda Bazel: make git_lfs_probe.py compatible with python 3.8 2024-05-07 12:44:28 +02:00
Jeroen Ketema
4eea214cb4 C++: Update test results after extractor changes 2024-05-07 11:10:07 +02:00
Jeroen Ketema
b8f62ae4d5 Merge pull request #16436 from jketema/jketema/throw-wrong
C++: Add test case that shows that no destructors are attached to unwinds
2024-05-07 11:07:24 +02:00
Michael Nebel
5fe3ab7890 Java: Prepare for inline test sharing with C#. 2024-05-07 10:38:24 +02:00
Mathias Vorreiter Pedersen
53c2d2f1e7 C++: Accept test changes. 2024-05-07 09:10:58 +01:00
Mathias Vorreiter Pedersen
07d51a55fd C++: Assign a meaningful definition location to the address of an SSA variable when it's available. 2024-05-07 09:10:58 +01:00
Mathias Vorreiter Pedersen
41b95a1938 Merge pull request #16416 from MathiasVP/add-iterator-to-expired-container-fp-2
C++: Add `cpp/iterator-to-expired-container` FP
2024-05-07 09:10:38 +01:00
Michael Nebel
cfb0a862c1 Merge pull request #16356 from michaelnebel/csharp/aligntelemetryimplementation
C#: Base telemetry Api Source/Sink nodes on abstract classes.
2024-05-07 09:16:38 +02:00
Jeroen Ketema
9b23635d0a C++: Add test case that shows that no destructors are attached to unwinds 2024-05-06 17:47:55 +02:00
Paolo Tranquilli
5c74bebe6c Merge pull request #16317 from github/redsun82/go
Go: add bazel build
2024-05-06 16:55:58 +02:00
Michael Nebel
757cf8d43a C#: Fix a comment typo. 2024-05-06 16:48:31 +02:00
Michael Nebel
b53fa0f7f3 Java: Ensure that it is the callable for the model origin that carries the comment containing the model. 2024-05-06 16:41:58 +02:00
Paolo Tranquilli
d85f81d699 Merge pull request #16435 from github/redsun82/buildifier
Bazel: move buildifier out of root `BUILD`
2024-05-06 16:41:25 +02:00
Paolo Tranquilli
7c7bdb2242 Merge pull request #16434 from github/redsun82/lfs
Bazel: fix lfs lazy rule when all objects are local
2024-05-06 16:40:59 +02:00
Paolo Tranquilli
92b3eda12d Bazel: move buildifier out of root BUILD
See https://github.com/github/codeql/pull/16428 for details as to why
this is necessary.
2024-05-06 16:00:05 +02:00
Michael Nebel
a8549d2e23 Java: Convert remaining tests to inline flow tests. 2024-05-06 15:54:01 +02:00
Paolo Tranquilli
54c9aea251 Bazel: fix lfs lazy rule when all objects are local 2024-05-06 15:47:43 +02:00
Paolo Tranquilli
73df4fa920 Go: fix Windows installation 2024-05-06 14:55:35 +02:00
Michael Nebel
95ddd6ec74 Java: Generalize the inline mad test to allow further re-use. 2024-05-06 13:57:18 +02:00
Michael Nebel
51e7f3be1a Java: Rename MaD to summary. 2024-05-06 13:03:38 +02:00
Paolo Tranquilli
5b184c179a Bazel/Go: add some comments 2024-05-06 12:48:01 +02:00
Paolo Tranquilli
cba4ba042c Merge branch 'main' into redsun82/go 2024-05-06 12:43:56 +02:00
Michael Nebel
a33393d452 Java: Delete old summary models expected output. 2024-05-06 11:02:04 +02:00
Michael Nebel
7cb8a6c52f Java: Inline models as data expected output as comments in the java files and add a test. 2024-05-06 11:01:23 +02:00
Michael Nebel
6815bcaa80 Java: Move param module into TestUtilities. 2024-05-06 10:19:39 +02:00
Michael Nebel
105984f7de Java: Make param module for MaD inline test. 2024-05-06 10:01:34 +02:00
Tom Hvitved
6233da3e40 Merge pull request #16399 from hvitved/csharp/unique-get-location
C#: Make `Element.getLocation` (mostly) functional
2024-05-05 20:18:19 +02:00
Mathias Vorreiter Pedersen
5d5e31378b Merge pull request #16415 from MathiasVP/cleanup-ir-variables 2024-05-03 18:49:11 +01:00
Jeroen Ketema
5cde3fa697 Merge pull request #16414 from jketema/range-based-for-loop-destructor-fix
C++: Correctly handle destructors at the end of range-based for-loops in the IR
2024-05-03 19:38:45 +02:00
erik-krogh
39a8b49222 add qhelp recommendation that you can use an obvious placeholder value 2024-05-03 19:37:31 +02:00
erik-krogh
b209fc67cb test the change to hardcoded-credentials 2024-05-03 19:34:18 +02:00
Paolo Tranquilli
77128de105 Bazel/Go: make installer work from internal repo and on windows
It turns out everything that is needed for the installer to work on
windows is enabling runfiles. This also requires symlinks to avoid
excessive copying of files.
2024-05-03 17:45:57 +02:00
Mathias Vorreiter Pedersen
7a1b85aa56 C++: Add FP test. 2024-05-03 16:04:21 +01:00
Geoffrey White
eb0621ab7a Merge pull request #16406 from geoffw0/test1
C++: Add test case for reassignment to UseAfterFree.ql.
2024-05-03 15:32:58 +01:00
Geoffrey White
c0cf1c7c8c Merge pull request #16402 from geoffw0/stringlifetimedoc
C++: Improve UseOfStringAfterLifetimeEnds doc.
2024-05-03 15:04:07 +01:00
Paolo Tranquilli
17990da205 Update go/extractor/BUILD.bazel
Co-authored-by: Cornelius Riemenschneider <cornelius@github.com>
2024-05-03 15:58:43 +02:00
Mathias Vorreiter Pedersen
d5475c4a89 C++: Delete predicate that I introduced by mistake. 2024-05-03 14:48:01 +01:00
Paolo Tranquilli
471303bd7c Bazel/Go: remove unneeded comment 2024-05-03 14:56:17 +02:00
Paolo Tranquilli
2132c7bf96 Bazel/Go: make @codeql//go:gen runnable from internal repo 2024-05-03 14:52:17 +02:00
Mathias Vorreiter Pedersen
7ca54a6f94 C++: Sync identical files. 2024-05-03 13:51:04 +01:00
Mathias Vorreiter Pedersen
e8cb8b4f81 C++: Convert IR variables to an abstract base class and use final alias'ing to ensure that we don't accidentially extend the abstract base class. 2024-05-03 13:50:50 +01:00
Jeroen Ketema
ba64cf3016 C++: Correctly handle destructors at the end of range-based for-loops in the IR 2024-05-03 14:38:37 +02:00
Tom Hvitved
3c91333d0b Address review comment 2024-05-03 14:09:41 +02:00
erik-krogh
d9e8e0e00a use some more standard values for credentials-kind for NodeJS client credentials 2024-05-03 13:58:37 +02:00
erik-krogh
ff85db36e2 exclude credentials as kind key from hardcoded-credentials when the key looks like a dummy password 2024-05-03 13:58:11 +02:00
Paolo Tranquilli
8f0b88497a Bazel/Go: be more specific in go/extractor/BUILD.bazel comments 2024-05-03 13:15:08 +02:00
Paolo Tranquilli
31c427e64c Bazel/Go: add more explanation in gen.py 2024-05-03 13:15:08 +02:00
Michael Nebel
e64a2d6c9c C#: Align telemetry implementation with Java. 2024-05-03 12:48:14 +02:00
Geoffrey White
807e6795a7 Apply suggestions from code review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2024-05-03 11:40:56 +01:00
Paolo Tranquilli
880262d462 Merge pull request #16393 from github/redsun82/lfs
Bazel: improved lazy lfs files
2024-05-03 12:37:41 +02:00
Michael Nebel
95ff5bae65 Merge pull request #16297 from michaelnebel/java/improveapitelemetry
Java: Identify more APIs as supported in the telemetry queries.
2024-05-03 12:34:19 +02:00
Paolo Tranquilli
6cbe16e0c2 Bazel: add progress reporting 2024-05-03 12:00:15 +02:00
Mathias Vorreiter Pedersen
75615f2817 Merge pull request #16373 from jketema/destructors-block-fix
C++: Update test results after extractor changes
2024-05-03 10:17:40 +01:00
Michael Nebel
c07bf65eb6 Update java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-05-03 11:13:05 +02:00
Michael Nebel
8def1c2c13 Java: Address review comments and some other code quality improvements. 2024-05-03 11:11:52 +02:00
Rasmus Wriedt Larsen
1b90f22e84 Merge pull request #16400 from RasmusWL/accept-ci-fixes
.expected script: Handle multiple job failure URLs
2024-05-03 09:58:47 +02:00
Paolo Tranquilli
ecdf62376d Bazel: clean up git_lfs_probe.py 2024-05-03 09:21:57 +02:00
Geoffrey White
f5431abb10 C++: Fix strncpy reference link (the old link was broken). 2024-05-02 17:37:52 +01:00
Geoffrey White
73cc211779 C++: Fix qhelp error. 2024-05-02 17:36:35 +01:00
Geoffrey White
08e08a2b3a C++: Qhelp punctuation. 2024-05-02 17:32:24 +01:00
Geoffrey White
657402b42f C++: Fix % character in qhelp. 2024-05-02 17:31:09 +01:00
Geoffrey White
ecbf7aef18 C++: Fix qhelp formatting. 2024-05-02 17:26:24 +01:00
Geoffrey White
669fc925e0 C++: Fix qhelp formatting. 2024-05-02 17:24:20 +01:00
Geoffrey White
8a04840f93 C++: Improve qhelp for IncorrectNotOperatorUsage.ql, including mention of an alternative fix. 2024-05-02 17:17:55 +01:00
Geoffrey White
f4e4e238ba C++: Add test cases for IncorrectNotOperatorUsage.ql. 2024-05-02 17:17:55 +01:00
Geoffrey White
8f682ef4e4 C++: Improve quality of some qhelp references. 2024-05-02 17:08:26 +01:00
Paolo Tranquilli
96d69ca49c Merge branch 'main' into redsun82/lfs 2024-05-02 18:05:50 +02:00
Geoffrey White
8a261b7e7a C++: Update StrncpyFlippedArgs.qhelp. 2024-05-02 17:04:49 +01:00
Paolo Tranquilli
daea674095 Bazel: cover standard https git credentials in git_lfs_probe.py 2024-05-02 18:02:22 +02:00
Geoffrey White
315f439135 C++: Add test case for reassignment to UseAfterFree.ql. 2024-05-02 16:40:28 +01:00
Geoffrey White
06d8892e03 C++: Rename an example file. 2024-05-02 16:39:59 +01:00
Geoffrey White
e22159ab5d C++: Update WrongTypeFormatArguments.qhelp. 2024-05-02 16:34:56 +01:00
Geoffrey White
355c7d9b41 C++: Rename an example file. 2024-05-02 16:34:49 +01:00
Paolo Tranquilli
00baccbc15 Go: autoformat 2024-05-02 17:08:23 +02:00
Paolo Tranquilli
81dea9f89a Merge branch 'main' into redsun82/go 2024-05-02 17:03:09 +02:00
Paolo Tranquilli
76067cb12d Go: skip X:nocoverageredesign printing by autobuilder built with bazel 2024-05-02 17:02:48 +02:00
Geoffrey White
e4cf7df38f C++: Edits to the .qhelp based on suggestions. 2024-05-02 16:00:31 +01:00
Geoffrey White
b8b3689251 C++: Autoformat. 2024-05-02 15:49:56 +01:00
Geoffrey White
0693bf9e75 C++: Improve UseOfStringAfterLifetimeEnds qhelp, references and alert message. 2024-05-02 15:40:27 +01:00
Paolo Tranquilli
1aafc377ad Revert "Go: write test go runtime version in a specific file"
This reverts commit abcd9165b4.
2024-05-02 16:22:24 +02:00
Paolo Tranquilli
abcd9165b4 Go: write test go runtime version in a specific file 2024-05-02 16:09:11 +02:00
Paolo Tranquilli
0bc6934bfc Go: rename pkg_files to something less confusing 2024-05-02 15:44:06 +02:00
Paolo Tranquilli
4ae82ac215 Go: add explanatory comment to extractor BUILD file 2024-05-02 15:40:13 +02:00
Rasmus Wriedt Larsen
ccad70897d Add --dont-wait option 2024-05-02 15:39:07 +02:00
Paolo Tranquilli
318d954536 Go: make //go:gen not clear by default, and clean on --force 2024-05-02 15:38:47 +02:00
Rasmus Wriedt Larsen
3239af9973 Handle multiple job failure URLs
CI has changed how jobs are being run 🤷
2024-05-02 15:31:56 +02:00
Mathias Vorreiter Pedersen
f7113e0105 Merge pull request #16345 from MathiasVP/cleanup-ssa-and-iterator-flow
C++: Clean up SSA and stop relying on memory edges for iterator flow
2024-05-02 14:21:25 +01:00
Paolo Tranquilli
ca2d94b297 Fix go pattern in .pre-commit-config.yaml 2024-05-02 15:15:45 +02:00
Rasmus Wriedt Larsen
2cff081f2b Minor fixes to CI script.
I had problems with proper resolution of codeql_repo_dir with old python installation, this fixes it
2024-05-02 15:13:50 +02:00
Paolo Tranquilli
9055d9567a Go: remove unused action (will be re-added later) 2024-05-02 15:08:51 +02:00
Tamás Vajk
f99cb3f649 Merge pull request #16396 from tamasvajk/buildless/opt-out-feed-check
C#: Change nuget feed responsiveness checking to be opt-out
2024-05-02 15:04:28 +02:00
Tamás Vajk
dfdd79d8cf Merge pull request #16395 from tamasvajk/buildless/logs1
C#: Add file path to log messages in assets.json parsing
2024-05-02 15:03:57 +02:00
Tom Hvitved
8ec4f0b5bd C#: Update expected test output 2024-05-02 14:53:02 +02:00
Mathias Vorreiter Pedersen
b912918d8b C++: Fix QLDoc. 2024-05-02 13:32:52 +01:00
Harry Maclean
ef88f3ed09 Merge pull request #16377 from hmac/hmac-sanitization-fp
Ruby: Fix StringSubstitutionCall charpred
2024-05-02 13:31:01 +01:00
Tom Hvitved
f5d4b2e6cd C#: Make Element.getLocation (mostly) functional 2024-05-02 14:16:34 +02:00
Tamas Vajk
d909f2bc4f Fix expected test output 2024-05-02 13:32:01 +02:00
Paolo Tranquilli
520a2c96ff Merge branch 'main' into redsun82/go 2024-05-02 12:41:51 +02:00
Paolo Tranquilli
12b9b805e2 Go: revert changes to make and CI to postpone them in a separate PR 2024-05-02 12:37:47 +02:00
Owen Mansel-Chan
9bfb189fa7 Merge pull request #16392 from owen-mc/external-flow/standardize-empty-model-yml
External flow: standardize `empty.model.yml`
2024-05-02 11:01:47 +01:00
Mathias Vorreiter Pedersen
322fa36359 C++: Fix QLDoc. 2024-05-02 10:37:49 +01:00
Mathias Vorreiter Pedersen
4a47e11a16 C++: Fix QLDoc. 2024-05-02 10:36:40 +01:00
Owen Mansel-Chan
83249cd9c2 Fix grammar in comment 2024-05-02 09:59:48 +01:00
Tamas Vajk
c6185b30ba C#: Change nuget feed responsiveness checking to be opt-out 2024-05-02 10:25:12 +02:00
Tamas Vajk
9ce08c586c C#: Add file path to log messages in assets.json parsing 2024-05-02 10:14:26 +02:00
Paolo Tranquilli
a8d3226e99 Merge branch 'main' into redsun82/go 2024-05-02 09:27:47 +02:00
Paolo Tranquilli
94212d103e Bazel/Go: remove apple_support
This was actually unnecessary, and requried a full Xcode installation
that we'd rather avoid.
2024-05-02 09:21:47 +02:00
Paolo Tranquilli
608791fd7f Bazel/Go: use native cross compilation for fat binaries 2024-05-02 09:21:43 +02:00
Harry Maclean
7d92ec5ddf Merge pull request #16378 from hmac/hmac-sanitization-wording
Ruby: fix wording in rb/request-without-cert-validation
2024-05-02 08:00:28 +01:00
Paolo Tranquilli
9157dee0db Bazel: integrate download_and_extract into lfs_smudge 2024-05-02 08:53:51 +02:00
Paolo Tranquilli
677520aa8e Bazel: improved lazy lfs files
This reintroduces lazy lfs file rules that were removed in
https://github.com/github/codeql/pull/16117, now improved.

The new rules will make the actual file download go through bazel's
download manager, which includes:
* caching into the repository cache
* sane limiting of concurrent downloads
* retries

The bulk of the work is done by `git_lfs_probe.py`, which will use the
LFS protocol (with authentication via SSH) to output short lived
download URLs that can be consumed by `repository_ctx.download`.
2024-05-02 06:38:26 +02:00
Owen Mansel-Chan
16dcc0969b Standardise comment explaining why extensible predicates must be defined 2024-05-01 22:00:01 +01:00
Owen Mansel-Chan
09e59ccf44 Name files with empty definitions of MaD extensible predicates to erowdmpty.model.yml 2024-05-01 21:39:38 +01:00
Mathias Vorreiter Pedersen
a8f2cbc2b1 Merge pull request #16331 from mario-campos/mario-campos/guarded-free
Cpp: new experimental query cpp/guarded-free
2024-05-01 17:32:44 +01:00
Harry Maclean
c00d0d302d Ruby: fix wording in rb/request-without-cert-validation 2024-05-01 17:25:58 +01:00
Mario Campos
5a7a1dc92e C++: forgot to import semmle.code.cpp.controlflow.Guards 2024-05-01 11:00:19 -05:00
Mario Campos
c480431ec0 C++: simplify cpp/guarded-free
This new form is more declarative by use of the `GuardCondition`. Thanks to the tireless effort of @MathiasVP!
2024-05-01 10:59:16 -05:00
Harry Maclean
f7fc2e0b00 Ruby: Fix StringSubstitutionCall charpred
Some missing parens meant this class targeted way more things than
intended.
2024-05-01 16:14:58 +01:00
Michael B. Gale
397e641f2f Merge pull request #16375 from github/mbg/go/allow-version-suffixes
Go: Allow version suffixes
2024-05-01 15:41:54 +01:00
Michael B. Gale
00cbfaf40e Go: Allow version suffixes 2024-05-01 15:00:45 +01:00
Mathias Vorreiter Pedersen
dc4604f5a5 Merge pull request #16367 from MathiasVP/better-documentation-for-iterator-to-expired-container
C++: Improve documentation for `cpp/iterator-to-expired-container`
2024-05-01 11:56:27 +01:00
Mathias Vorreiter Pedersen
40b6e1624f Update cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2024-05-01 11:41:23 +01:00
Mathias Vorreiter Pedersen
22e843abc6 Update cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2024-05-01 11:41:16 +01:00
Jeroen Ketema
3c70a2d7df C++: Update test results after extractor changes 2024-05-01 12:30:38 +02:00
Jeroen Ketema
541effb8cb Merge pull request #16369 from jketema/destructors-init-stmt
C++: Update IR tests after better handling of init statements in the extractor
2024-05-01 10:47:03 +02:00
Anders Schack-Mulligen
248ffa15a2 Merge pull request #16318 from aschackmull/dataflow/doublyboundedfasttc
Dataflow: Use doublyBoundedFastTC.
2024-05-01 09:48:23 +02:00
Jeroen Ketema
5843326b5c C++: Update IR tests after better handling of init statements in the extractor 2024-04-30 21:12:30 +02:00
Mathias Vorreiter Pedersen
3a2b0a2feb Merge pull request #16366 from MathiasVP/fix-ir-for-destructors-in-switch
C++: Fix IR destructor calls on `JumpStmt`s
2024-04-30 18:26:54 +01:00
Mathias Vorreiter Pedersen
07dd6d5c8d C++: Align 'break' statements. 2024-04-30 16:40:23 +01:00
Mathias Vorreiter Pedersen
708d12624f C++: Update documentation on 'cpp/iterator-to-expired-container'. 2024-04-30 16:32:32 +01:00
Mathias Vorreiter Pedersen
3eddd3114f C++: Accept test changes. 2024-04-30 16:14:30 +01:00
Mathias Vorreiter Pedersen
61ce7252e6 C++: Update the alert message in 'cpp/iterator-to-expired-container'. 2024-04-30 16:12:54 +01:00
Mathias Vorreiter Pedersen
b86aeb68ae Merge pull request #16364 from MathiasVP/ir-guards-with-boolean
C++: Support `IRGuard`s with no implicit boolean conversion
2024-04-30 16:07:32 +01:00
Mathias Vorreiter Pedersen
cf025e1924 C++: Accept test changes. 2024-04-30 15:47:53 +01:00
Mathias Vorreiter Pedersen
a200ced2d6 C++: Fix IR generation for jump statements. 2024-04-30 15:46:46 +01:00
Mathias Vorreiter Pedersen
c04e59611b Merge pull request #16355 from MathiasVP/promote-iterator-to-expired-container-out-of-experimental
C++: Promote `cpp/iterator-to-expired-container` out of experimental
2024-04-30 15:45:56 +01:00
Mathias Vorreiter Pedersen
c5a87c95d8 C++: Add tests that incorrectly call destructors twice. 2024-04-30 15:39:00 +01:00
Henry Mercer
797f675285 Merge pull request #16365 from github/post-release-prep/codeql-cli-2.17.2
Post-release preparation for codeql-cli-2.17.2
2024-04-30 14:51:01 +01:00
Mathias Vorreiter Pedersen
c32c810ae7 C++: Add a test with a 'short' type. 2024-04-30 14:48:21 +01:00
Mathias Vorreiter Pedersen
32fe084630 Update cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2024-04-30 14:42:30 +01:00
Ian Lynagh
0715c4ac5a Merge pull request #16341 from igfoo/igfoo/ODASA_BUILD_ERROR_DIR
Java: Remove support for deprecated ODASA_BUILD_ERROR_DIR env var
2024-04-30 13:18:51 +01:00
github-actions[bot]
99928b82ed Post-release preparation for codeql-cli-2.17.2 2024-04-30 12:15:35 +00:00
Rasmus Wriedt Larsen
377c6b4cc8 Merge pull request #12557 from felickz/patch-1
add  security-severity score to code scanning query list
2024-04-30 13:48:22 +02:00
Mathias Vorreiter Pedersen
2939c89f7a C++: Accept test changes. 2024-04-30 12:04:42 +01:00
Mathias Vorreiter Pedersen
bb6cc92728 C++: Support guards without implicit boolean conversions. 2024-04-30 12:04:35 +01:00
Mathias Vorreiter Pedersen
d736426529 C++: Support guards without implicit boolean conversions. 2024-04-30 11:45:58 +01:00
Mathias Vorreiter Pedersen
806d42852c C++: Add test in C file with pointer type guard. 2024-04-30 11:33:22 +01:00
Henry Mercer
8e251ee54f Merge pull request #16363 from github/release-prep/2.17.2
Release preparation for version 2.17.2
2024-04-30 11:29:06 +01:00
github-actions[bot]
5228d94d42 Release preparation for version 2.17.2 2024-04-30 10:25:51 +00:00
Geoffrey White
7d9f78b2de Merge pull request #16328 from geoffw0/pathinj
C++: Reduce duplication from cpp/path-injection
2024-04-30 10:06:40 +01:00
Paolo Tranquilli
2590d8a27f Merge branch 'main' into redsun82/go 2024-04-30 11:00:27 +02:00
Erik Krogh Kristensen
7e839792da Merge pull request #16330 from erik-krogh/del-deps-apr-2024
All: delete outdated deprecations
2024-04-30 10:43:39 +02:00
Paolo Tranquilli
98106f31c1 Merge pull request #16358 from github/redsun82/registry-override
Bazel: add empty registry override
2024-04-30 09:09:46 +02:00
Ian Lynagh
676bcf39a5 Java: Remove support for deprecated ODASA_BUILD_ERROR_DIR env var 2024-04-29 18:02:28 +01:00
Paolo Tranquilli
a28f87fff0 Bazel: add empty registry override
This will unblock work in parallel on two separate PRs that require
patching different modules.
2024-04-29 18:01:09 +02:00
Mathias Vorreiter Pedersen
94364f724e C++: Remove CP between all sinks and all states in 'cpp/iterator-to-expired-container'. 2024-04-29 16:46:00 +01:00
Harry Maclean
607ed2efb4 Merge pull request #16354 from hmac/hmac-incomplete-hostname-fp
Ruby: Reduce FPs for rb/incomplete-hostname-regexp
2024-04-29 14:40:44 +01:00
Michael Nebel
a304e2d8d6 Merge pull request #16248 from michaelnebel/csharp/groupsprojectbeforerestore
C#: Restore projects and collect dependencies for projects in the same folder sequentially.
2024-04-29 14:05:40 +02:00
Paolo Tranquilli
cb85a756a0 Bazel: patch apple_support to avoid registering its toolchain
This is done in order to avoid requiring a full Xcode installation, but
still being able to use other `apple_support` facilities, like
`universal_binary`.
2024-04-29 13:42:05 +02:00
Paolo Tranquilli
e7886d0e57 Bazel: add empty registry override 2024-04-29 13:39:30 +02:00
yoff
1c611fecde Merge pull request #16155 from yoff/python/MaD-method-arg-tests 2024-04-29 12:59:57 +02:00
Harry Maclean
51bc8e917e Ruby: Reduce FPs for rb/incomplete-hostname-regexp
Arguments in calls to `match[?]` should only be considered regular
expression interpretations if the `match` refers to the standard library
method, not a method in source code.
2024-04-29 11:19:34 +01:00
Mathias Vorreiter Pedersen
0fa5a1f274 C++: Add change note. 2024-04-29 11:17:53 +01:00
Paolo Tranquilli
15bb846a5f Go: add workaround for extractor pack windows installer 2024-04-29 12:17:47 +02:00
Mathias Vorreiter Pedersen
5c454bdd8c C++: Compute and add severity. 2024-04-29 11:09:42 +01:00
Mathias Vorreiter Pedersen
f194c70e8a C++: Set precision to medium. 2024-04-29 11:08:08 +01:00
Mathias Vorreiter Pedersen
179270ffc1 C++: Move 'cpp/iterator-to-expired-container' out of experimental. 2024-04-29 11:07:55 +01:00
Paolo Tranquilli
1f78882cdc Go: make windows checks happy 2024-04-29 11:27:16 +02:00
Paolo Tranquilli
f0f6c229f6 Go: fix regex in action for macOS 2024-04-29 11:16:30 +02:00
Paolo Tranquilli
2f6dd2ab81 Go: refactor workflows with shared action 2024-04-29 11:12:48 +02:00
Paolo Tranquilli
6ec223c515 Go: small cleanup in Makefile 2024-04-29 11:00:21 +02:00
Harry Maclean
8ccedd658a Merge pull request #16349 from hmac/hmac-uri-open
Ruby: Add URI.open example to rb/kernel-open qhelp
2024-04-29 09:42:39 +01:00
Mathias Vorreiter Pedersen
401717d739 C++: Add a missing taint step and accept test changes. 2024-04-29 09:38:42 +01:00
Mathias Vorreiter Pedersen
527409d05f C++: Fix iterator return types and accept test changes. 2024-04-29 09:38:42 +01:00
Mathias Vorreiter Pedersen
d3d2e2188d C++: Accept test changes. 2024-04-29 09:38:42 +01:00
Mathias Vorreiter Pedersen
141af7cc87 C++: Subclasses for both 'begin' and 'end'. 2024-04-29 09:38:42 +01:00
Mathias Vorreiter Pedersen
6e3dddede0 C++: Use iterator flow in dataflow. 2024-04-29 09:38:42 +01:00
Mathias Vorreiter Pedersen
683fe26034 C++: Add iterator flow based on dataflow SSA. 2024-04-29 09:38:41 +01:00
Mathias Vorreiter Pedersen
ea1b8a3999 C++: Implement 'getAnUltimateDefinition' on SSA definitions. 2024-04-29 09:38:41 +01:00
Mathias Vorreiter Pedersen
5f0efc19fa C++: Accept test changes. 2024-04-29 09:38:41 +01:00
Paolo Tranquilli
0dfd336729 Go: fix //go:gen on windows 2024-04-29 10:34:22 +02:00
Paolo Tranquilli
b0758fd109 Go: workaround for gazelle on macOS
See https://github.com/bazelbuild/bazel-gazelle/issues/1793 for details.
2024-04-29 10:29:53 +02:00
Michael Nebel
d62e888b86 C#: Code quality improvements. 2024-04-29 09:27:12 +02:00
Mathias Vorreiter Pedersen
50775d0c53 C++: Get rid of 'UseImpl' in TSsaDefOrUse so that it now only contains definitions. 2024-04-29 00:02:05 +01:00
Mathias Vorreiter Pedersen
9874d40d29 C++: Make 'getAddressOperand' available on 'DefImpl'. 2024-04-28 23:41:18 +01:00
Mathias Vorreiter Pedersen
044ee9b08a C++: Delete old iterator flow using memory edges. 2024-04-28 23:41:13 +01:00
Harry Maclean
8b23f6db10 Ruby: Add URI.open example to rb/kernel-open qhelp 2024-04-27 09:53:54 +01:00
Mathias Vorreiter Pedersen
3c2206728d Merge pull request #16333 from MathiasVP/fix-guards-on-pointers 2024-04-26 21:33:08 +01:00
Jeroen Ketema
8c87cb83bb Merge pull request #16342 from jketema/destructors-cleanup
C++: Don't emit destructor calls as part of 'TranslatedResultCopy' as this has already been done in some other 'TranslatedExpr'.
2024-04-26 22:05:00 +02:00
Mathias Vorreiter Pedersen
c9ce642e7a Merge pull request #16339 from MathiasVP/one-less-stage
C++: Remove a stage by properly caching `getResultIRType`
2024-04-26 16:52:16 +01:00
Mathias Vorreiter Pedersen
d18cdee0bc C++: Accept test changes. 2024-04-26 16:19:33 +01:00
Mathias Vorreiter Pedersen
b78537dd74 C++: Allow comparisons with pointer types in IRGuards. 2024-04-26 16:19:24 +01:00
Mathias Vorreiter Pedersen
e78091e9d0 C++: Sync identical files. 2024-04-26 16:19:02 +01:00
Mathias Vorreiter Pedersen
c10e00d389 C++: Add a subclass for constant instructions with pointer type. 2024-04-26 16:18:52 +01:00
Mathias Vorreiter Pedersen
bf61114284 C++: Add a test with pointer comparisons and float comparisons. 2024-04-26 16:17:45 +01:00
erik-krogh
800d7546fa change all the change-notes to breaking 2024-04-26 17:17:23 +02:00
Mathias Vorreiter Pedersen
d6c57de650 C++: Convert one of the tests to also test the 'absolute' versions of the GuardCondition predicates. 2024-04-26 16:11:19 +01:00
Paolo Tranquilli
d66494dcb0 Go: update go-tests-other-os.yml 2024-04-26 17:03:56 +02:00
Paolo Tranquilli
86d6b8ef21 Go: put back go setup 2024-04-26 16:54:14 +02:00
Mathias Vorreiter Pedersen
6147a38bea Merge pull request #16337 from MathiasVP/cache-second-level-scope
DataFlow: Cache `getSecondLevelScope`
2024-04-26 15:49:11 +01:00
Jeroen Ketema
67fb866efa C++: Update test results 2024-04-26 16:38:39 +02:00
Paolo Tranquilli
0f387eeac2 Go: add vendor update to //go:gen 2024-04-26 16:31:04 +02:00
Mathias Vorreiter Pedersen
4b0a217420 C++: Don't emit destructor calls as part of 'TranslatedResultCopy' as this has already been done in some other 'TranslatedExpr'. 2024-04-26 16:25:05 +02:00
Mario Campos
3195f0c828 Use more specific hasGlobalName() for stdlib function free(3)
Based on the CodeQL documentation's example of strncpy(3) and strlen(3): https://codeql.github.com/docs/codeql-language-guides/hash-consing-and-value-numbering/#example-query
2024-04-26 09:10:40 -05:00
Paolo Tranquilli
d98ccdfa06 Go: update workflow 2024-04-26 16:02:22 +02:00
Paolo Tranquilli
c8b02241af Merge branch 'main' into redsun82/go 2024-04-26 15:59:17 +02:00
Tamás Vajk
a707e14495 Merge pull request #16338 from tamasvajk/buildless/extractor-timing
C#: Store buildless extraction timing information and return in telem…
2024-04-26 15:59:01 +02:00
Paolo Tranquilli
146d84bbf8 Go: rework makefile 2024-04-26 15:20:33 +02:00
Tamas Vajk
1d45e3a558 C#: Store buildless extraction timing information and return in telemetry query 2024-04-26 14:59:31 +02:00
Mathias Vorreiter Pedersen
70e9c48a47 C++: Also implement the predicate in the raw stage. 2024-04-26 13:48:13 +01:00
Mathias Vorreiter Pedersen
dcc4ad2550 C++: Sync identical files. 2024-04-26 13:45:15 +01:00
Mathias Vorreiter Pedersen
54cadcfe9b C++: Forward to a cached predicate in a cached module instead of caching the predicate in 'Instruction.qll' to include it in the cached stage of the other predicates. 2024-04-26 13:44:45 +01:00
Rasmus Lerchedahl Petersen
3716b8c6a0 Python: update test to reflect correct behaviour
also add comments
2024-04-26 14:21:15 +02:00
Rasmus Lerchedahl Petersen
9f7edf378e Python: fix tests
The way to expose the `self` arguemnt
is to call an instance method on the class,
not on the instance...
2024-04-26 14:21:15 +02:00
Rasmus Lerchedahl Petersen
4f46ce1133 Python: add test for Argument[0, self, self:] for instance methods 2024-04-26 14:21:15 +02:00
Michael Nebel
f95b33049e Java: Improve the Api sources and sinks implementation. 2024-04-26 14:12:41 +02:00
Mathias Vorreiter Pedersen
2482519cd3 DataFlow: Cached second level scope. 2024-04-26 13:09:59 +01:00
Asger F
e44d4c45aa Merge pull request #16323 from asgerf/js/expose-internal-module-naming
JS: Expose InternalModuleNaming
2024-04-26 13:57:26 +02:00
Paolo Tranquilli
bfa189e2ac Go: use a dbscheme generated during the build in extractor-pack 2024-04-26 13:48:44 +02:00
Paolo Tranquilli
19b2e56d02 Go: group BUILD and dbscheme generation target 2024-04-26 13:38:10 +02:00
erik-krogh
14d88eb3ce add change-notes 2024-04-26 12:56:28 +02:00
Michael Nebel
b754706e44 Java: Update SupportedExternalApi expected test output. 2024-04-26 12:39:46 +02:00
Michael Nebel
9db32f4d26 Java: Identify more APIs as supported in the telemetry queries (as QL defined sinks). 2024-04-26 12:39:46 +02:00
Michael Nebel
acb2bbb2a3 Java: Identify more APIs as supported in the telemetry queries (as QL defined sources). 2024-04-26 12:39:46 +02:00
Michael Nebel
06f987ad58 Java: Add test example of a supported sink defined in QL. 2024-04-26 12:39:46 +02:00
Paolo Tranquilli
925a2cca7e Go: create whole extractor pack with bazel 2024-04-26 12:01:23 +02:00
Paolo Tranquilli
3ad9c026a5 Go: remove go_sdk.host
It's not required, and it can't work from the internal repository.
2024-04-26 11:20:47 +02:00
Paolo Tranquilli
7d9a68bf17 Go: wrap gazelle to regenerate from scratch and add header 2024-04-26 11:19:22 +02:00
erik-krogh
0468c5d0bf delete some tests of the old GVN library 2024-04-26 07:58:35 +02:00
erik-krogh
e55f2c5309 reinroduce GLobalValueNumbering.qll, that one was supposed to stay 2024-04-26 06:52:57 +02:00
Mario Campos
d7c784ef2f Initial commit of experimental query cpp/guarded-free. 2024-04-25 16:29:37 -05:00
erik-krogh
fb376a1cfd revert the deletion of explorationLimit. It'll be deleted along with the entire class later 2024-04-25 22:31:11 +02:00
erik-krogh
baa31e1469 delete outdated deprecations 2024-04-25 22:19:28 +02:00
Jeroen Ketema
8d962a5c28 Merge pull request #16322 from jketema/child-stmt
C++: Print destructors for children of statements that are again statements
2024-04-25 22:17:35 +02:00
Jeroen Ketema
389df35fb7 Merge branch 'main' into child-stmt 2024-04-25 21:47:06 +02:00
Geoffrey White
aa80dd41da Merge pull request #16329 from geoffw0/multibyte
C++: Fix typo.
2024-04-25 17:26:40 +01:00
Geoffrey White
553871678a C++: Change note. 2024-04-25 16:52:01 +01:00
Geoffrey White
15123a7b40 C++: Reduce duplication. 2024-04-25 16:49:22 +01:00
Geoffrey White
bbd80ec7a4 C++: Add some more test cases. 2024-04-25 16:44:52 +01:00
Florin Coada
1d421b3b28 Merge pull request #16326 from github/changedocs/2.17.1
Update codeql-changelog index.rst to include codeql-cli-2.17.1
2024-04-25 16:08:41 +01:00
Michael B. Gale
a87b991d78 Merge pull request #16325 from github/mbg/go/use-parse-instead-of-parselax 2024-04-25 15:20:36 +01:00
Geoffrey White
0fb71e24cb C++: Fix typo. 2024-04-25 14:52:56 +01:00
Florin Coada
14d04903dc Update codeql-changelog index.rst to include codeql-cli-2.17.1 2024-04-25 14:40:44 +01:00
Michael Nebel
181a063bb9 C#: Update expected test output. 2024-04-25 15:38:39 +02:00
Michael Nebel
131d0b911f C#: Inline dependency collection from asset files per group. 2024-04-25 15:35:08 +02:00
Michael Nebel
0124b0749f C#: Do not run dotnet restore in parallel for projects in the same folder. 2024-04-25 15:35:07 +02:00
Michael Nebel
6daf80cdd0 C#: Add integration test with multiple project files that have disjoint dependencies. 2024-04-25 15:35:07 +02:00
Tamás Vajk
9c139b591f Merge pull request #16321 from tamasvajk/buildless/log-messages
C#: Improve log messages
2024-04-25 15:12:37 +02:00
Michael B. Gale
b8cfff6d19 Go: Use Parse instead of ParseLax, since we need toolchain directives 2024-04-25 14:10:26 +01:00
Michael B. Gale
f33d7ee80d Go: Add unit tests for hasInvalidToolchainVersion 2024-04-25 14:09:47 +01:00
Michael B. Gale
15a6308c72 Go: Refactor condition for EmitInvalidToolchainVersion into separate function 2024-04-25 14:04:00 +01:00
Tamas Vajk
dd9183c345 Code quality improvements 2024-04-25 14:38:26 +02:00
Asger F
d0c9e3f7ad JS: Expose InternalModuleNaming 2024-04-25 13:33:17 +02:00
Asger F
9082972842 Merge pull request #16061 from RasmusWL/js-extractor-fix
JS: More robust CommonJS/ES2015 detection logic for extractor
2024-04-25 13:26:56 +02:00
Jeroen Ketema
05819a52ef C++: Print destructors for children of statements that are again statements 2024-04-25 13:25:42 +02:00
Nick Rolfe
116873c9b0 Merge pull request #16314 from github/nickrolfe/rb-sensitive
Ruby: do fewer regexp matches in SensitiveActions
2024-04-25 11:56:41 +01:00
Rasmus Wriedt Larsen
290b0fc4ab Merge pull request #16308 from asgerf/js/model-generation-quote
JS: Fix naming issue in generated models
2024-04-25 11:36:36 +02:00
Paolo Tranquilli
332d118d93 Merge pull request #16315 from github/redsun82/buildifier
Bazel: introduce buildifier formatting
2024-04-25 10:48:18 +02:00
Owen Mansel-Chan
82bbecc9c4 Merge pull request #16307 from owen-mc/go/fix/incomplete-hostname-regex
Go: fix flow through string concatenation in `go/incomplete-hostname-regex`
2024-04-25 09:43:51 +01:00
Tamas Vajk
15c1fd9425 C#: Improve log messages 2024-04-25 10:39:53 +02:00
Rasmus Wriedt Larsen
13ff9412a4 Merge pull request #16252 from RasmusWL/move-dataflow-tests
Python: Move dataflow tests out of experimental
2024-04-25 10:05:06 +02:00
Jeroen Ketema
9d24b5afa6 Merge pull request #16319 from jketema/ir-comment-fix
C++: Fix comment in IR test
2024-04-25 09:59:58 +02:00
Paolo Tranquilli
4ca8faa9c9 Go: introduce universal binaries on macOS 2024-04-25 09:27:59 +02:00
Paolo Tranquilli
393f6b7666 Go: add gazelle-generated BUILD files 2024-04-25 08:53:26 +02:00
Jeroen Ketema
95ec4e8d26 C++: Fix comment in IR test 2024-04-24 21:47:47 +02:00
Tom Hvitved
17e0cc5648 Merge pull request #16313 from hvitved/dataflow/fix-bad-join3
Data flow: Fix bad join
2024-04-24 17:09:14 +02:00
Paolo Tranquilli
196b6d7a1d CI: simplify reporting 2024-04-24 16:43:38 +02:00
Paolo Tranquilli
9def57250d CI: make reporting better 2024-04-24 16:35:50 +02:00
Paolo Tranquilli
9af9873e04 CI: add names to steps 2024-04-24 16:20:54 +02:00
Paolo Tranquilli
9f5782b67b Bazel: introduce buildifier formatting
This introduces tooling and enforcement for formatting bazel files.

The tooling is provided as a bazel run target from
[keith/buildifier-prebuilt](https://github.com/keith/buildifier-prebuilt).

This is used in a [`pre-commit`](https://pre-commit.com/) hook for those
having that installed. In turn this is used in a CI check. Relying on a
`pre-commit` action gives us easy checking that buildifying did not
change anything in the files and printing the diff, without having to
hand-roll the check ourselves.

This enforcement will make usage of gazelle easier, as gazelle itself
might reformat files, even outside of `go`. Having them properly
formatted will allow gazelle to leave them unchanged, without needing
to configure awkward exclude directives.
2024-04-24 15:49:48 +02:00
Owen Mansel-Chan
c61177cf42 Add change note 2024-04-24 14:21:59 +01:00
Owen Mansel-Chan
4140942479 Update tests 2024-04-24 14:19:33 +01:00
Owen Mansel-Chan
fd306ed79b Exclude constant names from sources to avoid duplicate results 2024-04-24 14:19:30 +01:00
Owen Mansel-Chan
8962307291 Add second good go file to tests 2024-04-24 14:19:29 +01:00
Owen Mansel-Chan
0000c72329 Remove attempt at avoiding duplicate alerts 2024-04-24 14:19:26 +01:00
Owen Mansel-Chan
3ef7a0932a Add flow through string concatenation 2024-04-24 14:19:25 +01:00
Tamás Vajk
f29d2c21bd Merge pull request #16312 from tamasvajk/fix/buildless/file-lookup
C#: Fix `global.json` and `packages.config` lookup
2024-04-24 15:05:55 +02:00
Tamás Vajk
3b44b131b9 Merge pull request #16311 from tamasvajk/fix/resx
C#: Do not download `Microsoft.CodeAnalysis.ResxSourceGenerator` when…
2024-04-24 13:49:55 +02:00
Tamas Vajk
4a97f95890 Improve code quality 2024-04-24 13:47:25 +02:00
Tamás Vajk
84ea3a9a2c Merge pull request #16310 from tamasvajk/buildless/nuget_versions
C#: Add integration test with multiple versions of the same nuget pac…
2024-04-24 13:33:27 +02:00
Nick Rolfe
8f2e51faa6 Ruby: do fewer regexp matches in SensitiveActions 2024-04-24 12:32:49 +01:00
Owen Mansel-Chan
f828f8ea65 Merge pull request #16250 from owen-mc/go/rename-untrusted-flow-source
Go: Rename `UntrustedFlowSource` to `RemoteFlowSource` to match other language libraries
2024-04-24 11:37:00 +01:00
Tom Hvitved
95d579d9de Data flow: Fix bad join
```
Evaluated relational algebra for predicate _DataFlowImpl::Impl<HardcodedDataInterpretedAsCodeQuery::HardcodedDataInterpretedAsCodeFlow::C>::ret__#count_range@d112335l with tuple counts:
            285176  ~2%    {3} r1 = SCAN `_DataFlowDispatch::DataFlowCall.getEnclosingCallable/0#dispred#b7b78b19_DataFlowImpl::Impl<Hardcoded__#shared` OUTPUT In.1, In.0, In.2
        3265592261  ~3%    {5}    | JOIN WITH `DataFlowImpl::Impl<HardcodedDataInterpretedAsCodeQuery::HardcodedDataInterpretedAsCodeFlow::C>::returnCallEdge1/4#d02cae42_2301#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.2, Rhs.2, Lhs.1, Rhs.3
             39070  ~8%    {6}    | JOIN WITH `DataFlowImplCommon::Cached::viableImplInCallContextExt/2#58e931ad` ON FIRST 3 OUTPUT Lhs.0, Lhs.3, Lhs.1, Lhs.2, Lhs.4, _
             39070  ~0%    {6}    | REWRITE WITH Out.5 := 1
                           return r1
```
2024-04-24 12:22:28 +02:00
Tamas Vajk
f3daba510b C#: Fix global.json and packages.config lookup 2024-04-24 11:57:45 +02:00
Tamas Vajk
88e67715a1 C#: Do not download Microsoft.CodeAnalysis.ResxSourceGenerator when there are no resx files to process 2024-04-24 11:53:29 +02:00
Tamas Vajk
53eb753346 C#: Add integration test with multiple versions of the same nuget package 2024-04-24 11:50:43 +02:00
Mathias Vorreiter Pedersen
037114b336 Merge pull request #16309 from geoffw0/newtests
C++: Add test cases
2024-04-24 10:06:51 +01:00
Nick Rolfe
af72c0848e Merge pull request #16306 from github/nickrolfe/js-sensitive
JS: do fewer regexp matches in SensitiveActions
2024-04-24 09:49:44 +01:00
Tamás Vajk
de58ee5a22 Merge pull request #16225 from tamasvajk/buildless/resx
C#: Add resource generator
2024-04-24 10:10:45 +02:00
Tom Hvitved
a1a93c7331 Merge pull request #16304 from hvitved/csharp/fix-bad-join
C#: Fix a bad join
2024-04-24 08:11:25 +02:00
Asger F
db07c162e4 JS: Allow generated models to use (package) 2024-04-23 20:25:55 +02:00
Asger F
9d00f660f1 Update ModelGeneration.expected 2024-04-23 20:08:21 +02:00
Owen Mansel-Chan
0311888fd4 Update change note
Co-authored-by: Michael B. Gale <mbg@github.com>
2024-04-23 19:07:02 +01:00
Asger F
e4f23b31c6 JS: Add quotes around package name to correct parsing 2024-04-23 20:04:23 +02:00
Geoffrey White
57a53891e9 C++: Effect of recent QL changes. 2024-04-23 18:12:05 +01:00
Geoffrey White
b6703bc25c C++: Add test cases inspired by QA results differences. 2024-04-23 18:06:12 +01:00
Nick Rolfe
003d208574 JS: do fewer regexp matches in SensitiveActions 2024-04-23 15:31:38 +01:00
Tom Hvitved
d8d7688f88 C#: Fix another bad join 2024-04-23 15:39:59 +02:00
Anders Schack-Mulligen
830b83f653 Dataflow: Use doublyBoundedFastTC. 2024-04-23 13:07:20 +02:00
Mathias Vorreiter Pedersen
3592e76269 Merge pull request #16302 from MathiasVP/fieldflowbranchlimit-follow-up-1
C++: `fieldFlowBranchLimit` follow-up (1)
2024-04-23 11:35:49 +01:00
Tom Hvitved
6aa4c5c187 C#: Fix a bad join 2024-04-23 11:47:55 +02:00
Michael B. Gale
fb8ee07b43 Merge pull request #16262 from github/dependabot/go_modules/go/ql/integration-tests/all-platforms/go/two-go-mods-not-nested/src/subdir1/golang.org/x/net-0.23.0 2024-04-23 10:44:54 +01:00
Michael B. Gale
4ccff1a630 Merge pull request #16263 from github/dependabot/go_modules/go/ql/integration-tests/all-platforms/go/ninja-sample/src/golang.org/x/net-0.23.0 2024-04-23 10:44:17 +01:00
Michael B. Gale
4b7160d4b2 Merge pull request #16267 from github/dependabot/go_modules/go/ql/integration-tests/all-platforms/go/go-mod-without-version/src/golang.org/x/net-0.23.0 2024-04-23 10:43:43 +01:00
Michael B. Gale
5cce5008a3 Merge pull request #16264 from github/dependabot/go_modules/go/ql/integration-tests/all-platforms/go/single-go-work-not-in-root/src/modules/subdir2/golang.org/x/net-0.23.0 2024-04-23 10:42:53 +01:00
Michael B. Gale
5b6ce56ca2 Merge pull request #16268 from github/dependabot/go_modules/go/ql/integration-tests/all-platforms/go/single-go-mod-not-in-root/src/subdir/golang.org/x/net-0.23.0 2024-04-23 10:42:24 +01:00
Michael B. Gale
2b81b6c323 Merge pull request #16265 from github/dependabot/go_modules/go/ql/integration-tests/all-platforms/go/mixed-layout/src/module/golang.org/x/net-0.23.0 2024-04-23 10:41:50 +01:00
Mathias Vorreiter Pedersen
a39d8b7c7c C++: Ensure that each node type gets mapped to an instruction by 'getAnInstruction'. 2024-04-23 09:44:30 +01:00
Rasmus Wriedt Larsen
1bc085c8f7 Python: Fixup for callGraphConfig 2024-04-23 09:42:35 +02:00
Rasmus Wriedt Larsen
bb00d6919a Python: Move dataflow TestUtil to importable location 2024-04-23 09:40:59 +02:00
Rasmus Wriedt Larsen
e0e405bb31 Python: replace dataflow-test location in files 2024-04-23 09:40:59 +02:00
Rasmus Wriedt Larsen
ce711f7d2f Python: Move dataflow tests out of experimental 2024-04-23 09:40:44 +02:00
Tamas Vajk
f20812d8ad Code quality improvement 2024-04-22 15:12:01 +02:00
Tamas Vajk
05f3c64172 Fix code review findings 2024-04-22 14:46:24 +02:00
dependabot[bot]
dae187eb0b Bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20200505041828-1ed23360d12c to 0.23.0.
- [Commits](https://github.com/golang/net/commits/v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 09:46:00 +00:00
dependabot[bot]
7f195d0257 Bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20200505041828-1ed23360d12c to 0.23.0.
- [Commits](https://github.com/golang/net/commits/v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 09:46:00 +00:00
dependabot[bot]
a8162baada Bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20200505041828-1ed23360d12c to 0.23.0.
- [Commits](https://github.com/golang/net/commits/v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 09:46:00 +00:00
dependabot[bot]
ef53184c10 Bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20200505041828-1ed23360d12c to 0.23.0.
- [Commits](https://github.com/golang/net/commits/v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 09:45:59 +00:00
dependabot[bot]
9d38c255f5 Bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20200505041828-1ed23360d12c to 0.23.0.
- [Commits](https://github.com/golang/net/commits/v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 09:45:58 +00:00
dependabot[bot]
4de4525528 Bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20200505041828-1ed23360d12c to 0.23.0.
- [Commits](https://github.com/golang/net/commits/v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 09:45:57 +00:00
Owen Mansel-Chan
79b4890794 Also rename .expected files 2024-04-18 14:17:04 +01:00
Owen Mansel-Chan
dc985c2c98 Add change note 2024-04-18 12:55:59 +01:00
Owen Mansel-Chan
b6f6bdc6f4 Make RemoteFlowAsSource private
`UntrustedFlowAsSource` should have been private. Since we are deprecating them anyway
we may as well make the replacement private (and make it use `instanceof`). The deprecation
comments have been updated.
2024-04-18 12:31:38 +01:00
Owen Mansel-Chan
a49b43fdf6 Add deprecated version of renamed public classes 2024-04-18 11:49:54 +01:00
Owen Mansel-Chan
317c335269 Rename test query files 2024-04-18 11:49:42 +01:00
Owen Mansel-Chan
db06c08141 Rename UntrustedSource to RemoteSource
Including renaming some files (in the experimental folder).
2024-04-18 11:49:30 +01:00
Owen Mansel-Chan
f39301f533 Fix "an remote" and similar
Preserve case, allow for "a `Remote" etc.
2024-04-18 11:49:18 +01:00
Owen Mansel-Chan
a6646021d0 Rename Untrusted Flow to Remote Flow
Not matching case but preserving original case.
2024-04-18 11:49:05 +01:00
Owen Mansel-Chan
d967b2baa3 Rename UntrustedFlowAsSource to RemoteFlowAsSource 2024-04-18 11:48:04 +01:00
Owen Mansel-Chan
a4df20da85 Rename UntrustedFlowSource to RemoteFlowSource
Relaxed match case requirement. Again skipped one instance in an old
change note.
2024-04-17 21:40:46 +01:00
Owen Mansel-Chan
81eaa6e327 Rename UntrustedFlowSource to RemoteFlowSource
Relaxed whole word requirement. Again skipped one instance in an old
change note.
2024-04-17 21:35:50 +01:00
Owen Mansel-Chan
5fba9895c6 Rename UntrustedFlowSource to RemoteFlowSource
Only the whole word. Skipped one instance in an old change note.
2024-04-17 21:27:32 +01:00
Asger F
64321b314f Merge branch 'main' into js-extractor-fix 2024-04-17 20:55:54 +02:00
Tamas Vajk
7b5f2c7d94 Fix expected test result on Windows 2024-04-17 15:12:51 +02:00
Tamas Vajk
41e666c724 Parse and use RootNamespace from project files 2024-04-17 14:01:52 +02:00
Tamas Vajk
88f6e04339 Make Resx extraction opt-in 2024-04-17 13:49:05 +02:00
Tamas Vajk
b560ab1a73 Fix condition for running dotnet source generators 2024-04-17 13:44:03 +02:00
Tamas Vajk
3626c814ac Run dotnet source generators on files grouped by projects 2024-04-17 13:40:03 +02:00
Tamas Vajk
bef556e208 Improve log messages 2024-04-17 11:46:27 +02:00
Tamas Vajk
5a5fc79b3b Fix regex to recognize prerelease version string 2024-04-17 11:46:27 +02:00
Tamas Vajk
9926c817de Code quality improvements 2024-04-17 11:46:26 +02:00
Tamas Vajk
53902c824d Fix integration tests 2024-04-17 11:46:26 +02:00
Tamas Vajk
3c5675b3fb WIP: Hardcode namespace for Resx generation 2024-04-17 11:46:26 +02:00
Tamas Vajk
3154a11b43 List members in resx test 2024-04-17 10:47:44 +02:00
Tamas Vajk
1ff4c0daf3 Restore and use Microsoft.CodeAnalysis.ResxSourceGenerator 2024-04-17 10:41:47 +02:00
Chad Bentz
f77f91ef49 move security-severity to end of column list in csv
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-04-16 16:02:15 -04:00
Tamas Vajk
79fe5f851b C#: Add resource generator 2024-04-16 14:30:53 +02:00
Tamas Vajk
407837afc4 C#: Refactor dotnet source generator execution 2024-04-16 10:20:23 +02:00
Chad Bentz
78ddb998a2 Merge branch 'main' into patch-1 2024-04-12 09:09:43 -04:00
Rasmus Wriedt Larsen
f33222c83b JS: Add change-note 2024-04-02 11:10:53 +02:00
Rasmus Wriedt Larsen
df463e51c1 JS: Extractor: Fix experimental flag value for NodeJSDetectorTests 2024-03-26 17:02:47 +01:00
Rasmus Wriedt Larsen
60944a9bcb JS: Accept new trap files
As I see it, these all seem to have invalid code initially anyway, but
this is definitely something a JS expert should review :)
2024-03-26 17:01:57 +01:00
Rasmus Wriedt Larsen
1d51d182ec JS: Extractor: Explain how to make replaceExpectedOutput work now with bazel 2024-03-26 17:01:57 +01:00
Rasmus Wriedt Larsen
04a0740ccb JS: Extractor: More robust ES2015 checking
Created shared AbstractDetector to not duplicate all the tedious logic
;)

I took inspiration from the tests in  `javascript/extractor/tests/esnext/input/dynamic-import.js`
2024-03-26 17:01:57 +01:00
Rasmus Wriedt Larsen
cd84500c56 JS: Extractor: Separate base detector logic into own file
Should hopefully make it easier to review these changes to have it split into its' own commit :)
2024-03-26 17:01:57 +01:00
Rasmus Wriedt Larsen
0515b12305 JS: Add example of bad NodeJS detection
Notice the TRAP lines

```
is_module(#20001)
is_es2015_module(#20001)
```
2024-03-25 11:36:21 +01:00
Chad Bentz
b12f4d97f8 Merge branch 'main' into patch-1 2024-01-17 09:25:28 -05:00
Chad Bentz
ee3085e15e Update generate-code-scanning-query-list.py 2023-12-14 14:09:14 -05:00
Chad Bentz
53e96e5adf Merge branch 'main' into patch-1 2023-10-25 10:00:16 -04:00
Chad Bentz
6f60eb9e1a Merge branch 'main' into patch-1 2023-08-09 14:31:26 -04:00
Chad Bentz
845f384df6 Merge branch 'main' into patch-1 2023-08-04 17:57:53 -04:00
Chad Bentz
39c52c9ecf add security-severity to code scanning query list 2023-03-16 11:27:23 -04:00
950 changed files with 17414 additions and 13255 deletions

View File

@@ -14,4 +14,11 @@ build:linux --cxxopt=-std=c++20
build:macos --cxxopt=-std=c++20 --cpu=darwin_x86_64
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
# this requires developer mode, but is required to have pack installer functioning
startup --windows_enable_symlinks
common --enable_runfiles
common --registry=file:///%workspace%/misc/bazel/registry
common --registry=https://bcr.bazel.build
try-import %workspace%/local.bazelrc

4
.bazelrc.internal Normal file
View File

@@ -0,0 +1,4 @@
# this file should contain bazel settings required to build things from `semmle-code`
common --registry=file:///%workspace%/ql/misc/bazel/registry
common --registry=https://bcr.bazel.build

28
.github/workflows/buildifier.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Check bazel formatting
on:
pull_request:
paths:
- "**.bazel"
- "**.bzl"
branches:
- main
- "rc/*"
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check bazel formatting
uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
with:
extra_args: >
buildifier --all-files 2>&1 ||
(
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel:buildifier"; exit 1
)

5
.lfsconfig Normal file
View File

@@ -0,0 +1,5 @@
[lfs]
# codeql is publicly forked by many users, and we don't want any LFS file polluting their working
# copies. We therefore exclude everything by default.
# For files required by bazel builds, use rules in `misc/bazel/lfs.bzl` to download them on demand.
fetchinclude = /nothing

View File

@@ -20,13 +20,22 @@ repos:
- id: autopep8
files: ^misc/codegen/.*\.py
- repo: https://github.com/warchant/pre-commit-buildifier
rev: 0.0.2
hooks:
- id: buildifier
- repo: local
hooks:
- id: buildifier
name: Format bazel files
files: \.(bazel|bzl)
language: system
entry: bazel run //misc/bazel:buildifier
pass_filenames: false
- id: go-gen
name: Check checked in generated files in go
files: ^go/.*
language: system
entry: bazel run //go:gen
pass_filenames: false
- id: codeql-format
name: Fix QL file formatting
files: \.qll?$

View File

@@ -13,7 +13,8 @@ local_path_override(
# see https://registry.bazel.build/ for a list of available packages
bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(name = "platforms", version = "0.0.9")
bazel_dep(name = "rules_go", version = "0.47.0")
bazel_dep(name = "rules_pkg", version = "0.10.1")
bazel_dep(name = "rules_nodejs", version = "6.0.3")
bazel_dep(name = "rules_python", version = "0.31.0")
@@ -21,6 +22,9 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
bazel_dep(name = "gazelle", version = "0.36.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
@@ -50,6 +54,9 @@ node.toolchain(
)
use_repo(node, "nodejs", "nodejs_toolchains")
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.22.2")
register_toolchains(
"@nodejs_toolchains//:all",
)

View File

@@ -362,7 +362,7 @@
"java/ql/lib/semmle/code/java/security/internal/EncryptionKeySizes.qll"
],
"Python model summaries test extension": [
"python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml"
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
]
}
}

View File

@@ -1,3 +1,20 @@
## 0.13.0
### Breaking Changes
* Deleted the deprecated `GlobalValueNumberingImpl.qll` implementation.
### New Features
* Models-as-Data support has been added for C/C++. This feature allows flow sources, sinks and summaries to be expressed in compact strings as an alternative to modelling each source / sink / summary with explicit QL. See `dataflow/ExternalFlow.qll` for documentation and specification of the model format, and `models/implementations/ZMQ.qll` for a simple example of models. Importing models from `.yml` is not yet supported.
### Minor Analysis Improvements
* Source models have been added for the standard library function `getc` (and variations).
* Source, sink and flow models for the ZeroMQ (ZMQ) networking library have been added.
* Parameters of functions without definitions now have `ParameterNode`s.
* The alias analysis used internally by various libraries has been improved to answer alias questions more conservatively. As a result, some queries may report fewer false positives.
## 0.12.11
No user-facing changes.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The alias analysis used internally by various libraries has been improved to answer alias questions more conservatively. As a result, some queries may report fewer false positives.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Parameters of functions without definitions now have `ParameterNode`s.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Source models have been added for the standard library function `getc` (and variations).

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Models-as-Data support has been added for C/C++. This feature allows flow sources, sinks and summaries to be expressed in compact strings as an alternative to modelling each source / sink / summary with explicit QL. See `dataflow/ExternalFlow.qll` for documentation and specification of the model format, and `models/implementations/ZMQ.qll` for a simple example of models. Importing models from `.yml` is not yet supported.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Source, sink and flow models for the ZeroMQ (ZMQ) networking library have been added.

View File

@@ -0,0 +1,16 @@
## 0.13.0
### Breaking Changes
* Deleted the deprecated `GlobalValueNumberingImpl.qll` implementation.
### New Features
* Models-as-Data support has been added for C/C++. This feature allows flow sources, sinks and summaries to be expressed in compact strings as an alternative to modelling each source / sink / summary with explicit QL. See `dataflow/ExternalFlow.qll` for documentation and specification of the model format, and `models/implementations/ZMQ.qll` for a simple example of models. Importing models from `.yml` is not yet supported.
### Minor Analysis Improvements
* Source models have been added for the standard library function `getc` (and variations).
* Source, sink and flow models for the ZeroMQ (ZMQ) networking library have been added.
* Parameters of functions without definitions now have `ParameterNode`s.
* The alias analysis used internally by various libraries has been improved to answer alias questions more conservatively. As a result, some queries may report fewer false positives.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.12.11
lastReleaseVersion: 0.13.0

View File

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

View File

@@ -463,6 +463,25 @@ class StmtNode extends AstNode {
}
}
/**
* A node representing a child of a `Stmt` that is itself a `Stmt`.
*/
class ChildStmtNode extends StmtNode {
Stmt childStmt;
ChildStmtNode() { exists(Stmt parent | parent.getAChild() = childStmt and childStmt = ast) }
override BaseAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
exists(int destructorIndex |
result.getAst() = childStmt.getImplicitDestructorCall(destructorIndex) and
childIndex =
destructorIndex + max(int index | exists(childStmt.getChild(index)) or index = 0) + 1
)
}
}
/**
* A node representing a `DeclStmt`.
*/
@@ -674,6 +693,13 @@ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
private string getChildAccessorWithoutConversions(Locatable parent, Element child) {
shouldPrintDeclaration(getAnEnclosingDeclaration(parent)) and
(
exists(Stmt s, int i | s.getChild(i) = parent |
exists(int n |
s.getChild(i).(Stmt).getImplicitDestructorCall(n) = child and
result = "getImplicitDestructorCall(" + n + ")"
)
)
or
exists(Stmt s | s = parent |
namedStmtChildPredicates(s, child, result)
or

View File

@@ -790,6 +790,27 @@ private predicate simple_comparison_eq(Instruction test, Operand op, int k, Abst
exists(switch.getSuccessor(case)) and
case.getValue().toInt() = k
)
or
// There's no implicit CompareInstruction in files compiled as C since C
// doesn't have implicit boolean conversions. So instead we check whether
// there's a branch on a value of pointer or integer type.
exists(ConditionalBranchInstruction branch, IRType type |
not test instanceof CompareInstruction and
type = test.getResultIRType() and
(type instanceof IRAddressType or type instanceof IRIntegerType) and
test = branch.getCondition() and
op.getDef() = test
|
// We'd like to also include a case such as:
// ```
// k = 1 and
// value.(BooleanValue).getValue() = true
// ```
// but all we know is that the value is non-zero in the true branch.
// So we can only conclude something in the false branch.
k = 0 and
value.(BooleanValue).getValue() = false
)
}
private predicate complex_eq(
@@ -1156,5 +1177,14 @@ private predicate add_eq(
)
}
private class IntegerOrPointerConstantInstruction extends ConstantInstruction {
IntegerOrPointerConstantInstruction() {
this instanceof IntegerConstantInstruction or
this instanceof PointerConstantInstruction
}
}
/** The int value of integer constant expression. */
private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() }
private int int_value(Instruction i) {
result = i.(IntegerOrPointerConstantInstruction).getValue().toInt()
}

View File

@@ -1596,12 +1596,23 @@ private Cpp::Stmt getAChainedBranch(Cpp::IfStmt s) {
)
}
private Instruction getInstruction(Node n) {
result = n.asInstruction() or
result = n.asOperand().getUse() or
result = n.(SsaPhiNode).getPhiNode().getBasicBlock().getFirstInstruction() or
n.(IndirectInstruction).hasInstructionAndIndirectionIndex(result, _) or
result = getInstruction(n.(PostUpdateNode).getPreUpdateNode())
private Instruction getAnInstruction(Node n) {
result = n.asInstruction()
or
not n instanceof InstructionNode and
result = n.asOperand().getUse()
or
result = n.(SsaPhiNode).getPhiNode().getBasicBlock().getFirstInstruction()
or
n.(IndirectInstruction).hasInstructionAndIndirectionIndex(result, _)
or
not n instanceof IndirectInstruction and
exists(Operand operand |
n.(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
result = operand.getUse()
)
or
result = getAnInstruction(n.(PostUpdateNode).getPreUpdateNode())
}
private newtype TDataFlowSecondLevelScope =
@@ -1647,10 +1658,318 @@ class DataFlowSecondLevelScope extends TDataFlowSecondLevelScope {
/** Gets a data-flow node nested within this scope. */
Node getANode() {
getInstruction(result).getAst().(Cpp::ControlFlowNode).getEnclosingStmt().getParentStmt*() =
getAnInstruction(result).getAst().(Cpp::ControlFlowNode).getEnclosingStmt().getParentStmt*() =
this.getAStmt()
}
}
/** Gets the second-level scope containing the node `n`, if any. */
DataFlowSecondLevelScope getSecondLevelScope(Node n) { result.getANode() = n }
/**
* Module that defines flow through iterators.
* For example,
* ```cpp
* auto it = v.begin();
* *it = source();
* ...
* sink(v[0]);
* ```
*/
module IteratorFlow {
private import codeql.ssa.Ssa as SsaImpl
private import semmle.code.cpp.models.interfaces.Iterator as Interface
private import semmle.code.cpp.models.implementations.Iterator as Impl
/**
* A variable of some type that can produce an iterator.
*/
class SourceVariable extends Ssa::SourceVariable {
SourceVariable() {
exists(Interface::GetIteratorFunction gets, Cpp::FunctionInput input, int i |
input.isParameterDerefOrQualifierObject(i) and
gets.getsIterator(input, _)
|
this.getType().stripType() = gets.getParameter(i).getType().stripType()
or
i = -1 and
this.getType().stripType() = gets.getDeclaringType()
)
}
}
private module SsaInput implements SsaImpl::InputSig<Location> {
import Ssa::InputSigCommon
class SourceVariable = IteratorFlow::SourceVariable;
/** A call to function that dereferences an iterator. */
private class IteratorPointerDereferenceCall extends CallInstruction {
IteratorPointerDereferenceCall() {
this.getStaticCallTarget() instanceof Impl::IteratorPointerDereferenceOperator
}
}
/** A call to a function that obtains an iterator. */
private class GetsIteratorCall extends CallInstruction {
GetsIteratorCall() { this.getStaticCallTarget() instanceof Impl::GetIteratorFunction }
}
/** A call to `operator++` or `operator--` on an iterator. */
private class IteratorCrementCall extends CallInstruction {
IteratorCrementCall() { this.getStaticCallTarget() instanceof Impl::IteratorCrementOperator }
}
/**
* Gets an ultimate definition of `def`.
*
* Note: Unlike `def.getAnUltimateDefinition()` this predicate also
* traverses back through iterator increment and decrement operations.
*/
private Ssa::Def getAnUltimateDefinition(Ssa::Def def) {
result = def.getAnUltimateDefinition()
or
exists(IRBlock bb, int i, IteratorCrementCall crementCall, Ssa::SourceVariable sv |
crementCall = def.getValue().asInstruction().(StoreInstruction).getSourceValue() and
sv = def.getSourceVariable() and
bb.getInstruction(i) = crementCall and
Ssa::ssaDefReachesRead(sv, result.asDef(), bb, i)
)
}
/**
* Holds if `write` is an instruction that writes to address `address`
*/
private predicate isIteratorWrite(Instruction write, Operand address) {
exists(Ssa::DefImpl writeDef, IRBlock bb, int i |
writeDef.hasIndexInBlock(bb, i, _) and
bb.getInstruction(i) = write and
address = writeDef.getAddressOperand()
)
}
/**
* Holds if `writeToDeref` is a write to an iterator that was obtained
* by `beginCall`. That is, the following instruction sequence holds:
* ```cpp
* it = container.begin(); // or a similar iterator-obtaining function call
* ...
* *it = value;
* ```
*/
private predicate isIteratorStoreInstruction(
GetsIteratorCall beginCall, Instruction writeToDeref
) {
exists(
StoreInstruction beginStore, IRBlock bbStar, int iStar, Ssa::Def def,
IteratorPointerDereferenceCall starCall, Ssa::Def ultimate, Operand address
|
isIteratorWrite(writeToDeref, address) and
operandForFullyConvertedCall(address, starCall) and
bbStar.getInstruction(iStar) = starCall and
Ssa::ssaDefReachesRead(_, def.asDef(), bbStar, iStar) and
ultimate = getAnUltimateDefinition*(def) and
beginStore = ultimate.getValue().asInstruction() and
operandForFullyConvertedCall(beginStore.getSourceValueOperand(), beginCall)
)
}
/**
* Holds if `(bb, i)` contains a write to an iterator that may have been obtained
* by calling `begin` (or related functions) on the variable `v`.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
certain = false and
exists(GetsIteratorCall beginCall, Instruction writeToDeref, IRBlock bbQual, int iQual |
isIteratorStoreInstruction(beginCall, writeToDeref) and
bb.getInstruction(i) = writeToDeref and
bbQual.getInstruction(iQual) = beginCall and
Ssa::variableRead(bbQual, iQual, v, _)
)
}
/** Holds if `(bb, i)` reads the container variable `v`. */
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
Ssa::variableRead(bb, i, v, certain)
}
}
private module IteratorSsa = SsaImpl::Make<Location, SsaInput>;
cached
private newtype TSsaDef =
TDef(IteratorSsa::DefinitionExt def) or
TPhi(PhiNode phi)
abstract private class SsaDef extends TSsaDef {
/** Gets a textual representation of this element. */
string toString() { none() }
/** Gets the underlying non-phi definition or use. */
IteratorSsa::DefinitionExt asDef() { none() }
/** Gets the underlying phi node. */
PhiNode asPhi() { none() }
/** Gets the location of this element. */
abstract Location getLocation();
}
private class Def extends TDef, SsaDef {
IteratorSsa::DefinitionExt def;
Def() { this = TDef(def) }
final override IteratorSsa::DefinitionExt asDef() { result = def }
final override Location getLocation() { result = this.getImpl().getLocation() }
/** Gets the variable written to by this definition. */
final SourceVariable getSourceVariable() { result = def.getSourceVariable() }
override string toString() { result = def.toString() }
/**
* Holds if this definition (or use) has index `index` in block `block`,
* and is a definition (or use) of the variable `sv`.
*/
predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
def.definesAt(sv, block, index, _)
}
private Ssa::DefImpl getImpl() {
exists(IRBlock bb, int i |
this.hasIndexInBlock(bb, i, _) and
result.hasIndexInBlock(bb, i)
)
}
/** Gets the value written by this definition (i.e., the "right-hand side"). */
Node0Impl getValue() { result = this.getImpl().getValue() }
/** Gets the indirection index of this definition. */
int getIndirectionIndex() { result = this.getImpl().getIndirectionIndex() }
}
private class Phi extends TPhi, SsaDef {
PhiNode phi;
Phi() { this = TPhi(phi) }
final override PhiNode asPhi() { result = phi }
final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
override string toString() { result = phi.toString() }
SsaIteratorNode getNode() { result.getIteratorFlowNode() = phi }
}
private class PhiNode extends IteratorSsa::DefinitionExt {
PhiNode() {
this instanceof IteratorSsa::PhiNode or
this instanceof IteratorSsa::PhiReadNode
}
SsaIteratorNode getNode() { result.getIteratorFlowNode() = this }
}
cached
private module IteratorSsaCached {
cached
predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
IteratorSsa::adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
or
exists(PhiNode phi |
IteratorSsa::lastRefRedefExt(_, sv, bb1, i1, phi) and
phi.definesAt(sv, bb2, i2, _)
)
}
cached
Node getAPriorDefinition(IteratorSsa::DefinitionExt next) {
exists(IRBlock bb, int i, SourceVariable sv, IteratorSsa::DefinitionExt def |
IteratorSsa::lastRefRedefExt(pragma[only_bind_into](def), pragma[only_bind_into](sv),
pragma[only_bind_into](bb), pragma[only_bind_into](i), next) and
nodeToDefOrUse(result, sv, bb, i, _)
)
}
}
/** The set of nodes necessary for iterator flow. */
class IteratorFlowNode instanceof PhiNode {
/** Gets a textual representation of this node. */
string toString() { result = super.toString() }
/** Gets the type of this node. */
DataFlowType getType() {
exists(Ssa::SourceVariable sv |
super.definesAt(sv, _, _, _) and
result = sv.getType()
)
}
/** Gets the `Declaration` that contains this block. */
Declaration getFunction() { result = super.getBasicBlock().getEnclosingFunction() }
/** Gets the locatino of this node. */
Location getLocation() { result = super.getBasicBlock().getLocation() }
}
private import IteratorSsaCached
private predicate defToNode(Node node, Def def, boolean uncertain) {
(
nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
or
nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
) and
uncertain = false
}
private predicate nodeToDefOrUse(
Node node, SourceVariable sv, IRBlock bb, int i, boolean uncertain
) {
exists(Def def |
def.hasIndexInBlock(bb, i, sv) and
defToNode(node, def, uncertain)
)
or
useToNode(bb, i, sv, node) and
uncertain = false
}
private predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
exists(PhiNode phi |
phi.definesAt(sv, bb, i, _) and
nodeTo = phi.getNode()
)
or
exists(Ssa::UseImpl use |
use.hasIndexInBlock(bb, i, sv) and
nodeTo = use.getNode()
)
}
/**
* Holds if `nodeFrom` flows to `nodeTo` in a single step.
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
exists(
Node nFrom, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2, boolean uncertain
|
adjacentDefRead(bb1, i1, sv, bb2, i2) and
nodeToDefOrUse(nFrom, sv, bb1, i1, uncertain) and
useToNode(bb2, i2, sv, nodeTo)
|
if uncertain = true
then
nodeFrom =
[
nFrom,
getAPriorDefinition(any(IteratorSsa::DefinitionExt next | next.definesAt(sv, bb1, i1, _)))
]
else nFrom = nodeFrom
)
}
}

View File

@@ -46,6 +46,7 @@ private newtype TIRDataFlowNode =
Ssa::isModifiableByCall(operand, indirectionIndex)
} or
TSsaPhiNode(Ssa::PhiNode phi) or
TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
} or
@@ -653,6 +654,30 @@ class SsaPhiNode extends Node, TSsaPhiNode {
predicate isPhiRead() { phi.isPhiRead() }
}
/**
* INTERNAL: do not use.
*
* Dataflow nodes necessary for iterator flow
*/
class SsaIteratorNode extends Node, TSsaIteratorNode {
IteratorFlow::IteratorFlowNode node;
SsaIteratorNode() { this = TSsaIteratorNode(node) }
/** Gets the phi node associated with this node. */
IteratorFlow::IteratorFlowNode getIteratorFlowNode() { result = node }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = node.getFunction() }
override DataFlowType getType() { result = node.getType() }
final override Location getLocationImpl() { result = node.getLocation() }
override string toStringImpl() { result = node.toString() }
}
/**
* INTERNAL: do not use.
*
@@ -1190,11 +1215,11 @@ class UninitializedNode extends Node {
LocalVariable v;
UninitializedNode() {
exists(Ssa::Def def |
exists(Ssa::Def def, Ssa::SourceVariable sv |
def.getIndirectionIndex() = 0 and
def.getValue().asInstruction() instanceof UninitializedInstruction and
Ssa::nodeToDefOrUse(this, def, _) and
v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
Ssa::defToNode(this, def, sv, _, _, _) and
v = sv.getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
)
}
@@ -2151,6 +2176,8 @@ private module Cached {
// Def-use/Use-use flow
Ssa::ssaFlow(nodeFrom, nodeTo)
or
IteratorFlow::localFlowStep(nodeFrom, nodeTo)
or
// Operand -> Instruction flow
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
or

View File

@@ -246,14 +246,6 @@ private module IteratorIndirections {
baseType = super.getValueType()
}
override predicate isAdditionalDereference(Instruction deref, Operand address) {
exists(CallInstruction call |
operandForFullyConvertedCall(getAUse(deref), call) and
this = call.getStaticCallTarget().getClassAndName("operator*") and
address = call.getThisArgumentOperand()
)
}
override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) {
exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() |
this = call.getStaticCallTarget().getClassAndName("operator=") and
@@ -262,16 +254,6 @@ private module IteratorIndirections {
)
}
override predicate isAdditionalTaintStep(Node node1, Node node2) {
exists(CallInstruction call |
// Taint through `operator+=` and `operator-=` on iterators.
call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and
node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and
node1.(IndirectOperand).hasOperandAndIndirectionIndex(call.getArgumentOperand(0), _) and
node1.getType().getUnspecifiedType() = this
)
}
override predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
// This is a bit annoying: Consider the following snippet:
// ```
@@ -589,230 +571,6 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns
cached
private module Cached {
private import semmle.code.cpp.models.interfaces.Iterator as Interfaces
private import semmle.code.cpp.models.implementations.Iterator as Iterator
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
/**
* Holds if `next` is a instruction with a memory result that potentially
* updates the memory produced by `prev`.
*/
private predicate memorySucc(Instruction prev, Instruction next) {
prev = next.(ChiInstruction).getTotal()
or
// Phi inputs can be inexact.
prev = next.(PhiInstruction).getAnInputOperand().getAnyDef()
or
prev = next.(CopyInstruction).getSourceValue()
or
exists(ReadSideEffectInstruction read |
next = read.getPrimaryInstruction() and
isAdditionalConversionFlow(_, next) and
prev = read.getSideEffectOperand().getAnyDef()
)
}
/**
* Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
* that is used for a write operation that writes the value `value`. The `memory` instruction
* represents the memory that the IR's SSA analysis determined was read by the call to `operator*`.
*
* The `numberOfLoads` integer represents the number of dereferences this write corresponds to
* on the underlying container that produced the iterator.
*/
private predicate isChiAfterIteratorDef(
Instruction memory, Operand iteratorDerefAddress, Node0Impl value, int numberOfLoads
) {
exists(
BaseSourceVariableInstruction iteratorBase, ReadSideEffectInstruction read,
Operand iteratorAddress
|
numberOfLoads >= 0 and
isDef(_, value, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
iteratorBase.getResultType() instanceof Interfaces::Iterator and
isDereference(iteratorAddress.getDef(), read.getArgumentDef().getAUse(), _) and
memory = read.getSideEffectOperand().getAnyDef()
)
}
private predicate isSource(Instruction instr, Operand iteratorAddress, int numberOfLoads) {
getAUse(instr) = iteratorAddress and
exists(BaseSourceVariableInstruction iteratorBase |
iteratorBase.getResultType() instanceof Interfaces::Iterator and
not iteratorBase.getResultType() instanceof Cpp::PointerType and
isUse(_, iteratorAddress, iteratorBase, numberOfLoads - 1, 0)
)
}
private predicate isSink(Instruction instr, CallInstruction call) {
getAUse(instr).(ArgumentOperand).getCall() = call and
// Only include operations that may modify the object that the iterator points to.
// The following is a non-exhaustive list of things that may modify the value of the
// iterator, but never the value of what the iterator points to.
// The more things we can exclude here, the faster the small dataflow-like analysis
// done by `convertsIntoArgument` will converge.
not exists(Function f | f = call.getStaticCallTarget() |
f instanceof Iterator::IteratorCrementOperator or
f instanceof Iterator::IteratorBinaryArithmeticOperator or
f instanceof Iterator::IteratorAssignArithmeticOperator or
f instanceof Iterator::IteratorCrementMemberOperator or
f instanceof Iterator::IteratorBinaryArithmeticMemberOperator or
f instanceof Iterator::IteratorAssignArithmeticMemberOperator or
f instanceof Iterator::IteratorAssignmentMemberOperator
)
}
private predicate convertsIntoArgumentFwd(Instruction instr) {
isSource(instr, _, _)
or
exists(Instruction prev | convertsIntoArgumentFwd(prev) |
conversionFlow(unique( | | getAUse(prev)), instr, false, _)
)
}
private predicate convertsIntoArgumentRev(Instruction instr) {
convertsIntoArgumentFwd(instr) and
(
isSink(instr, _)
or
exists(Instruction next | convertsIntoArgumentRev(next) |
conversionFlow(unique( | | getAUse(instr)), next, false, _)
)
)
}
private predicate convertsIntoArgument(
Operand iteratorAddress, CallInstruction call, int numberOfLoads
) {
exists(Instruction iteratorAddressDef |
isSource(iteratorAddressDef, iteratorAddress, numberOfLoads) and
isSink(iteratorAddressDef, call) and
convertsIntoArgumentRev(pragma[only_bind_into](iteratorAddressDef))
)
}
private predicate isChiAfterIteratorArgument(
Instruction memory, Operand iteratorAddress, int numberOfLoads
) {
// Ideally, `iteratorAddress` would be an `ArgumentOperand`, but there might be
// various conversions applied to it before it becomes an argument.
// So we do a small amount of flow to find the call that the iterator is passed to.
exists(CallInstruction call | convertsIntoArgument(iteratorAddress, call, numberOfLoads) |
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = call and
read.getSideEffectOperand().getAnyDef() = memory
)
or
exists(LoadInstruction load |
iteratorAddress.getDef() = load and
memory = load.getSourceValueOperand().getAnyDef()
)
)
}
/**
* Holds if `iterator` is a `StoreInstruction` that stores the result of some function
* returning an iterator into an address computed started at `containerBase`.
*
* For example, given a declaration like `std::vector<int>::iterator it = v.begin()`,
* the `iterator` will be the `StoreInstruction` generated by the write to `it`, and
* `containerBase` will be the address of `v`.
*/
private predicate isChiAfterBegin(
BaseSourceVariableInstruction containerBase, StoreInstruction iterator
) {
exists(
CallInstruction getIterator, Iterator::GetIteratorFunction getIteratorFunction,
IO::FunctionInput input, int i
|
getIterator = iterator.getSourceValue() and
getIteratorFunction = getIterator.getStaticCallTarget() and
getIteratorFunction.getsIterator(input, _) and
isDef(_, any(Node0Impl n | n.asInstruction() = iterator), _, _, 1, 0) and
input.isParameterDerefOrQualifierObject(i) and
isUse(_, getIterator.getArgumentOperand(i), containerBase, 0, 0)
)
}
/**
* Holds if `iteratorAddress` is an address of an iterator that is used for
* a read operation. The `memory` instruction represents the memory that
* the IR's SSA analysis determined was read by the call to `operator*`.
*
* Finally, the `numberOfLoads` integer represents the number of dereferences
* this read corresponds to on the underlying container that produced the iterator.
*/
private predicate isChiBeforeIteratorUse(
Operand iteratorAddress, Instruction memory, int numberOfLoads
) {
exists(
BaseSourceVariableInstruction iteratorBase, LoadInstruction load,
ReadSideEffectInstruction read, Operand iteratorDerefAddress
|
numberOfLoads >= 0 and
isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
isUse(_, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
iteratorBase.getResultType() instanceof Interfaces::Iterator and
load.getSourceAddressOperand() = iteratorDerefAddress and
read.getPrimaryInstruction() = load.getSourceAddress() and
memory = read.getSideEffectOperand().getAnyDef()
)
}
/**
* Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
* that is used for a write operation that writes the value `value` to a container that
* created the iterator. `container` represents the base of the address of the container
* that was used to create the iterator.
*/
cached
predicate isIteratorDef(
BaseSourceVariableInstruction container, Operand iteratorDerefAddress, Node0Impl value,
int numberOfLoads, int indirectionIndex
) {
exists(Instruction memory, Instruction begin, int upper, int ind |
isChiAfterIteratorDef(memory, iteratorDerefAddress, value, numberOfLoads) and
memorySucc*(begin, memory) and
isChiAfterBegin(container, begin) and
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
ind = numberOfLoads + [1 .. upper] and
indirectionIndex = ind - (numberOfLoads + 1)
)
}
/**
* Holds if `iteratorAddress` is an address of an iterator that is used for a
* read operation to read a value from a container that created the iterator.
* `container` represents the base of the address of the container that was used
* to create the iterator.
*/
cached
predicate isIteratorUse(
BaseSourceVariableInstruction container, Operand iteratorAddress, int numberOfLoads,
int indirectionIndex
) {
// Direct use
exists(Instruction begin, Instruction memory, int upper, int ind |
isChiBeforeIteratorUse(iteratorAddress, memory, numberOfLoads) and
memorySucc*(begin, memory) and
isChiAfterBegin(container, begin) and
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
ind = numberOfLoads + [1 .. upper] and
indirectionIndex = ind - (numberOfLoads + 1)
)
or
// Use through function output
exists(Instruction memory, Instruction begin, int upper, int ind |
isChiAfterIteratorArgument(memory, iteratorAddress, numberOfLoads) and
memorySucc*(begin, memory) and
isChiAfterBegin(container, begin) and
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
ind = numberOfLoads + [1 .. upper] and
indirectionIndex = ind - (numberOfLoads - 1)
)
}
/** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
private predicate isConversion(Operand op) {
exists(Instruction def, Operand use |

View File

@@ -17,18 +17,11 @@ private import Imports::IRType
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
class IRVariable extends TIRVariable {
abstract private class AbstractIRVariable extends TIRVariable {
Language::Declaration func;
IRVariable() {
this = TIRUserVariable(_, _, func) or
this = TIRTempVariable(func, _, _, _) or
this = TIRStringLiteral(func, _, _, _) or
this = TIRDynamicInitializationFlag(func, _, _)
}
/** Gets a textual representation of this element. */
string toString() { none() }
abstract string toString();
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -49,13 +42,13 @@ class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
Language::LanguageType getLanguageType() { none() }
abstract Language::LanguageType getLanguageType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
Language::AST getAst() { none() }
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
@@ -64,7 +57,7 @@ class IRVariable extends TIRVariable {
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
string getUniqueId() { none() }
abstract string getUniqueId();
/**
* Gets the source location of this variable.
@@ -74,7 +67,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
final IRFunction getEnclosingIRFunction() { result.getFunction() = this.getEnclosingFunction() }
/**
* Gets the function that references this variable.
@@ -82,10 +75,18 @@ class IRVariable extends TIRVariable {
final Language::Declaration getEnclosingFunction() { result = func }
}
/**
* A variable referenced by the IR for a function.
*
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
final class IRVariable = AbstractIRVariable;
/**
* A user-declared variable referenced by the IR for a function.
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
Language::Variable var;
Language::LanguageType type;
@@ -114,26 +115,29 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
class IRAutomaticVariable extends IRVariable {
IRAutomaticVariable() {
exists(Language::Variable var |
this = TIRUserVariable(var, _, func) and
Language::isVariableAutomatic(var)
)
or
this = TIRTempVariable(func, _, _, _)
}
abstract private class AbstractIRAutomaticVariable extends AbstractIRVariable { }
/**
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
final class IRAutomaticVariable = AbstractIRAutomaticVariable;
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
private class AbstractIRAutomaticUserVariable extends IRUserVariable, AbstractIRAutomaticVariable {
override Language::AutomaticVariable var;
final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
final override Language::AutomaticVariable getVariable() { result = var }
}
final class IRAutomaticUserVariable = AbstractIRAutomaticUserVariable;
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
@@ -151,16 +155,10 @@ class IRStaticUserVariable extends IRUserVariable {
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
class IRGeneratedVariable extends IRVariable {
abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
Language::AST ast;
Language::LanguageType type;
IRGeneratedVariable() {
this = TIRTempVariable(func, ast, _, type) or
this = TIRStringLiteral(func, ast, type, _) or
this = TIRDynamicInitializationFlag(func, ast, type)
}
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
@@ -196,12 +194,20 @@ class IRGeneratedVariable extends IRVariable {
string getBaseString() { none() }
}
/**
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
final class IRGeneratedVariable = AbstractIRGeneratedVariable;
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of a function, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
class IRTempVariable extends AbstractIRGeneratedVariable, AbstractIRAutomaticVariable,
TIRTempVariable
{
TempVariableTag tag;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
@@ -241,7 +247,7 @@ class IRThrowVariable extends IRTempVariable {
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
* function that accepts a variable number of arguments.
*/
class IREllipsisVariable extends IRTempVariable, IRParameter {
class IREllipsisVariable extends IRTempVariable, AbstractIRParameter {
IREllipsisVariable() { tag = EllipsisTempVar() }
final override string toString() { result = "#ellipsis" }
@@ -252,7 +258,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
/**
* A temporary variable generated to hold the `this` pointer.
*/
class IRThisVariable extends IRTempVariable, IRParameter {
class IRThisVariable extends IRTempVariable, AbstractIRParameter {
IRThisVariable() { tag = ThisTempVar() }
final override string toString() { result = "#this" }
@@ -264,7 +270,7 @@ class IRThisVariable extends IRTempVariable, IRParameter {
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
class IRStringLiteral extends AbstractIRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
@@ -288,7 +294,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
* used to model the runtime initialization of static local variables in C++, as well as static
* fields in C#.
*/
class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
class IRDynamicInitializationFlag extends AbstractIRGeneratedVariable, TIRDynamicInitializationFlag {
Language::Variable var;
IRDynamicInitializationFlag() {
@@ -314,24 +320,24 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
class IRParameter extends IRAutomaticVariable {
IRParameter() {
this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
or
this = TIRTempVariable(_, _, ThisTempVar(), _)
or
this = TIRTempVariable(_, _, EllipsisTempVar(), _)
}
abstract private class AbstractIRParameter extends AbstractIRAutomaticVariable {
/**
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
*/
int getIndex() { none() }
}
/**
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
final class IRParameter = AbstractIRParameter;
/**
* An IR variable representing a positional parameter.
*/
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
class IRPositionalParameter extends AbstractIRParameter, AbstractIRAutomaticUserVariable {
IRPositionalParameter() { this.getVariable() instanceof Language::Parameter }
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
}

View File

@@ -247,8 +247,7 @@ class Instruction extends Construction::TStageInstruction {
* Gets the type of the result produced by this instruction. If the instruction does not produce
* a result, its result type will be `IRVoidType`.
*/
cached
final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() }
final IRType getResultIRType() { result = Construction::getInstructionResultIRType(this) }
/**
* Gets the type of the result produced by this instruction. If the
@@ -995,9 +994,8 @@ class ConstantInstruction extends ConstantValueInstruction {
*/
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
exists(IRType resultType |
resultType = this.getResultIRType() and
(resultType instanceof IRIntegerType or resultType instanceof IRBooleanType)
exists(IRType resultType | resultType = this.getResultIRType() |
resultType instanceof IRIntegerType or resultType instanceof IRBooleanType
)
}
}
@@ -1009,6 +1007,17 @@ class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType }
}
/**
* An instruction whose result is a constant value of a pointer type.
*/
class PointerConstantInstruction extends ConstantInstruction {
PointerConstantInstruction() {
exists(IRType resultType | resultType = this.getResultIRType() |
resultType instanceof IRAddressType or resultType instanceof IRFunctionAddressType
)
}
}
/**
* An instruction whose result is the address of a string literal.
*/

View File

@@ -429,6 +429,11 @@ private module Cached {
instr = unreachedInstruction(_) and result = Language::getVoidType()
}
cached
IRType getInstructionResultIRType(Instruction instr) {
result = instr.getResultLanguageType().getIRType()
}
/**
* Holds if `opcode` is the opcode that specifies the operation performed by `instr`.
*

View File

@@ -17,18 +17,11 @@ private import Imports::IRType
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
class IRVariable extends TIRVariable {
abstract private class AbstractIRVariable extends TIRVariable {
Language::Declaration func;
IRVariable() {
this = TIRUserVariable(_, _, func) or
this = TIRTempVariable(func, _, _, _) or
this = TIRStringLiteral(func, _, _, _) or
this = TIRDynamicInitializationFlag(func, _, _)
}
/** Gets a textual representation of this element. */
string toString() { none() }
abstract string toString();
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -49,13 +42,13 @@ class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
Language::LanguageType getLanguageType() { none() }
abstract Language::LanguageType getLanguageType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
Language::AST getAst() { none() }
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
@@ -64,7 +57,7 @@ class IRVariable extends TIRVariable {
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
string getUniqueId() { none() }
abstract string getUniqueId();
/**
* Gets the source location of this variable.
@@ -74,7 +67,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
final IRFunction getEnclosingIRFunction() { result.getFunction() = this.getEnclosingFunction() }
/**
* Gets the function that references this variable.
@@ -82,10 +75,18 @@ class IRVariable extends TIRVariable {
final Language::Declaration getEnclosingFunction() { result = func }
}
/**
* A variable referenced by the IR for a function.
*
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
final class IRVariable = AbstractIRVariable;
/**
* A user-declared variable referenced by the IR for a function.
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
Language::Variable var;
Language::LanguageType type;
@@ -114,26 +115,29 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
class IRAutomaticVariable extends IRVariable {
IRAutomaticVariable() {
exists(Language::Variable var |
this = TIRUserVariable(var, _, func) and
Language::isVariableAutomatic(var)
)
or
this = TIRTempVariable(func, _, _, _)
}
abstract private class AbstractIRAutomaticVariable extends AbstractIRVariable { }
/**
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
final class IRAutomaticVariable = AbstractIRAutomaticVariable;
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
private class AbstractIRAutomaticUserVariable extends IRUserVariable, AbstractIRAutomaticVariable {
override Language::AutomaticVariable var;
final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
final override Language::AutomaticVariable getVariable() { result = var }
}
final class IRAutomaticUserVariable = AbstractIRAutomaticUserVariable;
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
@@ -151,16 +155,10 @@ class IRStaticUserVariable extends IRUserVariable {
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
class IRGeneratedVariable extends IRVariable {
abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
Language::AST ast;
Language::LanguageType type;
IRGeneratedVariable() {
this = TIRTempVariable(func, ast, _, type) or
this = TIRStringLiteral(func, ast, type, _) or
this = TIRDynamicInitializationFlag(func, ast, type)
}
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
@@ -196,12 +194,20 @@ class IRGeneratedVariable extends IRVariable {
string getBaseString() { none() }
}
/**
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
final class IRGeneratedVariable = AbstractIRGeneratedVariable;
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of a function, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
class IRTempVariable extends AbstractIRGeneratedVariable, AbstractIRAutomaticVariable,
TIRTempVariable
{
TempVariableTag tag;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
@@ -241,7 +247,7 @@ class IRThrowVariable extends IRTempVariable {
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
* function that accepts a variable number of arguments.
*/
class IREllipsisVariable extends IRTempVariable, IRParameter {
class IREllipsisVariable extends IRTempVariable, AbstractIRParameter {
IREllipsisVariable() { tag = EllipsisTempVar() }
final override string toString() { result = "#ellipsis" }
@@ -252,7 +258,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
/**
* A temporary variable generated to hold the `this` pointer.
*/
class IRThisVariable extends IRTempVariable, IRParameter {
class IRThisVariable extends IRTempVariable, AbstractIRParameter {
IRThisVariable() { tag = ThisTempVar() }
final override string toString() { result = "#this" }
@@ -264,7 +270,7 @@ class IRThisVariable extends IRTempVariable, IRParameter {
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
class IRStringLiteral extends AbstractIRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
@@ -288,7 +294,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
* used to model the runtime initialization of static local variables in C++, as well as static
* fields in C#.
*/
class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
class IRDynamicInitializationFlag extends AbstractIRGeneratedVariable, TIRDynamicInitializationFlag {
Language::Variable var;
IRDynamicInitializationFlag() {
@@ -314,24 +320,24 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
class IRParameter extends IRAutomaticVariable {
IRParameter() {
this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
or
this = TIRTempVariable(_, _, ThisTempVar(), _)
or
this = TIRTempVariable(_, _, EllipsisTempVar(), _)
}
abstract private class AbstractIRParameter extends AbstractIRAutomaticVariable {
/**
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
*/
int getIndex() { none() }
}
/**
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
final class IRParameter = AbstractIRParameter;
/**
* An IR variable representing a positional parameter.
*/
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
class IRPositionalParameter extends AbstractIRParameter, AbstractIRAutomaticUserVariable {
IRPositionalParameter() { this.getVariable() instanceof Language::Parameter }
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
}

View File

@@ -247,8 +247,7 @@ class Instruction extends Construction::TStageInstruction {
* Gets the type of the result produced by this instruction. If the instruction does not produce
* a result, its result type will be `IRVoidType`.
*/
cached
final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() }
final IRType getResultIRType() { result = Construction::getInstructionResultIRType(this) }
/**
* Gets the type of the result produced by this instruction. If the
@@ -995,9 +994,8 @@ class ConstantInstruction extends ConstantValueInstruction {
*/
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
exists(IRType resultType |
resultType = this.getResultIRType() and
(resultType instanceof IRIntegerType or resultType instanceof IRBooleanType)
exists(IRType resultType | resultType = this.getResultIRType() |
resultType instanceof IRIntegerType or resultType instanceof IRBooleanType
)
}
}
@@ -1009,6 +1007,17 @@ class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType }
}
/**
* An instruction whose result is a constant value of a pointer type.
*/
class PointerConstantInstruction extends ConstantInstruction {
PointerConstantInstruction() {
exists(IRType resultType | resultType = this.getResultIRType() |
resultType instanceof IRAddressType or resultType instanceof IRFunctionAddressType
)
}
}
/**
* An instruction whose result is the address of a string literal.
*/

View File

@@ -377,6 +377,10 @@ CppType getInstructionResultType(TStageInstruction instr) {
result = getVoidType()
}
IRType getInstructionResultIRType(Instruction instr) {
result = instr.getResultLanguageType().getIRType()
}
predicate getInstructionOpcode(Opcode opcode, TStageInstruction instr) {
getInstructionTranslatedElement(instr).hasInstruction(opcode, getInstructionTag(instr), _)
or

View File

@@ -538,6 +538,11 @@ class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy {
final override predicate producesExprResult() { any() }
private TranslatedCoreExpr getOperand() { result.getExpr() = expr }
override predicate handlesDestructorsExplicitly() {
// The destructor calls will already have been generated by the translation of `expr`.
any()
}
}
class TranslatedCommaExpr extends TranslatedNonConstantExpr {

View File

@@ -1163,6 +1163,8 @@ class TranslatedForStmt extends TranslatedLoop {
class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override RangeBasedForStmt stmt;
override predicate handlesDestructorsExplicitly() { any() }
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
@@ -1216,6 +1218,19 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
or
child = this.getUpdate() and
result = this.getCondition().getFirstInstruction(kind)
or
exists(int destructorId |
destructorId >= this.getFirstDestructorCallIndex() and
child = this.getChild(destructorId) and
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
)
or
exists(int lastDestructorIndex |
lastDestructorIndex =
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
child = this.getChild(lastDestructorIndex) and
result = this.getParent().getChildSuccessor(this, kind)
)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -1231,7 +1246,9 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getParent().getChildSuccessor(this, kind)
if this.hasAnImplicitDestructorCall()
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
}
private TranslatedDeclStmt getRangeVariableDeclStmt() {
@@ -1276,6 +1293,11 @@ class TranslatedJumpStmt extends TranslatedStmt {
override JumpStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
// The first instruction is a destructor call, if any.
result = this.getChildInternal(0).getFirstInstruction(kind)
or
// Otherwise, the first (and only) instruction is a `NoOp`
not exists(this.getChildInternal(0)) and
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
@@ -1284,7 +1306,20 @@ class TranslatedJumpStmt extends TranslatedStmt {
result = this.getInstruction(OnlyInstructionTag())
}
override TranslatedElement getChildInternal(int id) { none() }
private TranslatedCall getTranslatedImplicitDestructorCall(int id) {
result.getExpr() = stmt.getImplicitDestructorCall(id)
}
override TranslatedElement getLastChild() {
result =
this.getTranslatedImplicitDestructorCall(max(int id |
exists(stmt.getImplicitDestructorCall(id))
))
}
override TranslatedElement getChildInternal(int id) {
result = this.getTranslatedImplicitDestructorCall(id)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
@@ -1297,7 +1332,19 @@ class TranslatedJumpStmt extends TranslatedStmt {
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction(kind)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
final override predicate handlesDestructorsExplicitly() { any() }
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
exists(int id | child = this.getChildInternal(id) |
// Transition to the next destructor call, if any.
result = this.getChildInternal(id + 1).getFirstInstruction(kind)
or
// And otherwise, exit this element by flowing to the target of the jump.
not exists(this.getChildInternal(id + 1)) and
kind instanceof GotoEdge and
result = this.getInstruction(OnlyInstructionTag())
)
}
}
private EdgeKind getCaseEdge(SwitchCase switchCase) {

View File

@@ -17,18 +17,11 @@ private import Imports::IRType
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
class IRVariable extends TIRVariable {
abstract private class AbstractIRVariable extends TIRVariable {
Language::Declaration func;
IRVariable() {
this = TIRUserVariable(_, _, func) or
this = TIRTempVariable(func, _, _, _) or
this = TIRStringLiteral(func, _, _, _) or
this = TIRDynamicInitializationFlag(func, _, _)
}
/** Gets a textual representation of this element. */
string toString() { none() }
abstract string toString();
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -49,13 +42,13 @@ class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
Language::LanguageType getLanguageType() { none() }
abstract Language::LanguageType getLanguageType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
Language::AST getAst() { none() }
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
@@ -64,7 +57,7 @@ class IRVariable extends TIRVariable {
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
string getUniqueId() { none() }
abstract string getUniqueId();
/**
* Gets the source location of this variable.
@@ -74,7 +67,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
final IRFunction getEnclosingIRFunction() { result.getFunction() = this.getEnclosingFunction() }
/**
* Gets the function that references this variable.
@@ -82,10 +75,18 @@ class IRVariable extends TIRVariable {
final Language::Declaration getEnclosingFunction() { result = func }
}
/**
* A variable referenced by the IR for a function.
*
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
final class IRVariable = AbstractIRVariable;
/**
* A user-declared variable referenced by the IR for a function.
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
Language::Variable var;
Language::LanguageType type;
@@ -114,26 +115,29 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
class IRAutomaticVariable extends IRVariable {
IRAutomaticVariable() {
exists(Language::Variable var |
this = TIRUserVariable(var, _, func) and
Language::isVariableAutomatic(var)
)
or
this = TIRTempVariable(func, _, _, _)
}
abstract private class AbstractIRAutomaticVariable extends AbstractIRVariable { }
/**
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
final class IRAutomaticVariable = AbstractIRAutomaticVariable;
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
private class AbstractIRAutomaticUserVariable extends IRUserVariable, AbstractIRAutomaticVariable {
override Language::AutomaticVariable var;
final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
final override Language::AutomaticVariable getVariable() { result = var }
}
final class IRAutomaticUserVariable = AbstractIRAutomaticUserVariable;
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
@@ -151,16 +155,10 @@ class IRStaticUserVariable extends IRUserVariable {
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
class IRGeneratedVariable extends IRVariable {
abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
Language::AST ast;
Language::LanguageType type;
IRGeneratedVariable() {
this = TIRTempVariable(func, ast, _, type) or
this = TIRStringLiteral(func, ast, type, _) or
this = TIRDynamicInitializationFlag(func, ast, type)
}
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
@@ -196,12 +194,20 @@ class IRGeneratedVariable extends IRVariable {
string getBaseString() { none() }
}
/**
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
final class IRGeneratedVariable = AbstractIRGeneratedVariable;
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of a function, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
class IRTempVariable extends AbstractIRGeneratedVariable, AbstractIRAutomaticVariable,
TIRTempVariable
{
TempVariableTag tag;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
@@ -241,7 +247,7 @@ class IRThrowVariable extends IRTempVariable {
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
* function that accepts a variable number of arguments.
*/
class IREllipsisVariable extends IRTempVariable, IRParameter {
class IREllipsisVariable extends IRTempVariable, AbstractIRParameter {
IREllipsisVariable() { tag = EllipsisTempVar() }
final override string toString() { result = "#ellipsis" }
@@ -252,7 +258,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
/**
* A temporary variable generated to hold the `this` pointer.
*/
class IRThisVariable extends IRTempVariable, IRParameter {
class IRThisVariable extends IRTempVariable, AbstractIRParameter {
IRThisVariable() { tag = ThisTempVar() }
final override string toString() { result = "#this" }
@@ -264,7 +270,7 @@ class IRThisVariable extends IRTempVariable, IRParameter {
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
class IRStringLiteral extends AbstractIRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
@@ -288,7 +294,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
* used to model the runtime initialization of static local variables in C++, as well as static
* fields in C#.
*/
class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
class IRDynamicInitializationFlag extends AbstractIRGeneratedVariable, TIRDynamicInitializationFlag {
Language::Variable var;
IRDynamicInitializationFlag() {
@@ -314,24 +320,24 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
class IRParameter extends IRAutomaticVariable {
IRParameter() {
this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
or
this = TIRTempVariable(_, _, ThisTempVar(), _)
or
this = TIRTempVariable(_, _, EllipsisTempVar(), _)
}
abstract private class AbstractIRParameter extends AbstractIRAutomaticVariable {
/**
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
*/
int getIndex() { none() }
}
/**
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
final class IRParameter = AbstractIRParameter;
/**
* An IR variable representing a positional parameter.
*/
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
class IRPositionalParameter extends AbstractIRParameter, AbstractIRAutomaticUserVariable {
IRPositionalParameter() { this.getVariable() instanceof Language::Parameter }
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
}

View File

@@ -247,8 +247,7 @@ class Instruction extends Construction::TStageInstruction {
* Gets the type of the result produced by this instruction. If the instruction does not produce
* a result, its result type will be `IRVoidType`.
*/
cached
final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() }
final IRType getResultIRType() { result = Construction::getInstructionResultIRType(this) }
/**
* Gets the type of the result produced by this instruction. If the
@@ -995,9 +994,8 @@ class ConstantInstruction extends ConstantValueInstruction {
*/
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
exists(IRType resultType |
resultType = this.getResultIRType() and
(resultType instanceof IRIntegerType or resultType instanceof IRBooleanType)
exists(IRType resultType | resultType = this.getResultIRType() |
resultType instanceof IRIntegerType or resultType instanceof IRBooleanType
)
}
}
@@ -1009,6 +1007,17 @@ class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType }
}
/**
* An instruction whose result is a constant value of a pointer type.
*/
class PointerConstantInstruction extends ConstantInstruction {
PointerConstantInstruction() {
exists(IRType resultType | resultType = this.getResultIRType() |
resultType instanceof IRAddressType or resultType instanceof IRFunctionAddressType
)
}
}
/**
* An instruction whose result is the address of a string literal.
*/

View File

@@ -429,6 +429,11 @@ private module Cached {
instr = unreachedInstruction(_) and result = Language::getVoidType()
}
cached
IRType getInstructionResultIRType(Instruction instr) {
result = instr.getResultLanguageType().getIRType()
}
/**
* Holds if `opcode` is the opcode that specifies the operation performed by `instr`.
*

View File

@@ -560,7 +560,7 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
TaintFunction, SideEffectFunction, AliasFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and
(input.isParameterDeref(0) or input.isParameter(0)) and
output.isQualifierObject()
}
@@ -579,17 +579,34 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
}
/**
* A `begin` member function, or a related function, that returns an iterator.
*/
class BeginFunction extends MemberFunction {
BeginFunction() {
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and
this.getType().getUnspecifiedType() instanceof Iterator
}
}
/**
* An `end` member function, or a related function, that returns an iterator.
*/
class EndFunction extends MemberFunction {
EndFunction() {
this.hasName(["end", "cend", "rend", "crend"]) and
this.getType().getUnspecifiedType() instanceof Iterator
}
}
/**
* A `begin` or `end` member function, or a related member function, that
* returns an iterator.
*/
class BeginOrEndFunction extends MemberFunction {
BeginOrEndFunction() {
this.hasName([
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
"cbefore_begin"
]) and
this.getType().getUnspecifiedType() instanceof Iterator
this instanceof BeginFunction or
this instanceof EndFunction
}
}

View File

@@ -1,616 +0,0 @@
/**
* DEPRECATED: This library has been replaced with a newer version which
* provides better performance and precision. Use
* `semmle.code.cpp.valuenumbering.GlobalValueNumbering` instead.
*
* Provides an implementation of Global Value Numbering.
* See https://en.wikipedia.org/wiki/Global_value_numbering
*
* The predicate `globalValueNumber` converts an expression into a `GVN`,
* which is an abstract type representing the value of the expression. If
* two expressions have the same `GVN` then they compute the same value.
* For example:
*
* ```
* void f(int x, int y) {
* g(x+y, x+y);
* }
* ```
*
* In this example, both arguments in the call to `g` compute the same value,
* so both arguments have the same `GVN`. In other words, we can find
* this call with the following query:
*
* ```
* from FunctionCall call, GVN v
* where v = globalValueNumber(call.getArgument(0))
* and v = globalValueNumber(call.getArgument(1))
* select call
* ```
*
* The analysis is conservative, so two expressions might have different
* `GVN`s even though the actually always compute the same value. The most
* common reason for this is that the analysis cannot prove that there
* are no side-effects that might cause the computed value to change.
*/
/*
* Note to developers: the correctness of this module depends on the
* definitions of GVN, globalValueNumber, and analyzableExpr being kept in
* sync with each other. If you change this module then make sure that the
* change is symmetric across all three.
*/
import cpp
private import semmle.code.cpp.controlflow.SSA
/**
* Holds if the result is a control flow node that might change the
* value of any global variable. This is used in the implementation
* of `GVN_OtherVariable`, because we need to be quite conservative when
* we assign a value number to a global variable. For example:
*
* ```
* x = g+1;
* dosomething();
* y = g+1;
* ```
*
* It is not safe to assign the same value number to both instances
* of `g+1` in this example, because the call to `dosomething` might
* change the value of `g`.
*/
private ControlFlowNode nodeWithPossibleSideEffect() {
result instanceof Call
or
// If the lhs of an assignment is not analyzable by SSA, then
// we need to treat the assignment as having a possible side-effect.
result instanceof Assignment and not result instanceof SsaDefinition
or
result instanceof CrementOperation and not result instanceof SsaDefinition
or
exists(LocalVariable v |
result = v.getInitializer().getExpr() and not result instanceof SsaDefinition
)
or
result instanceof AsmStmt
}
/**
* Gets the entry node of the control flow graph of which `node` is a
* member.
*/
cached
private ControlFlowNode getControlFlowEntry(ControlFlowNode node) {
result = node.getControlFlowScope().getEntryPoint() and
result.getASuccessor*() = node
}
/**
* Holds if there is a control flow edge from `src` to `dst` or
* if `dst` is an expression with a possible side-effect. The idea
* is to treat side effects as entry points in the control flow
* graph so that we can use the dominator tree to find the most recent
* side-effect.
*/
private predicate sideEffectCfg(ControlFlowNode src, ControlFlowNode dst) {
src.getASuccessor() = dst
or
// Add an edge from the entry point to any node that might have a side
// effect.
dst = nodeWithPossibleSideEffect() and
src = getControlFlowEntry(dst)
}
/**
* Holds if `dominator` is the immediate dominator of `node` in
* the side-effect CFG.
*/
private predicate iDomEffect(ControlFlowNode dominator, ControlFlowNode node) =
idominance(functionEntry/1, sideEffectCfg/2)(_, dominator, node)
/**
* Gets the most recent side effect. To be more precise, `result` is a
* dominator of `node` and no side-effects can occur between `result` and
* `node`.
*
* `sideEffectCFG` has an edge from the function entry to every node with a
* side-effect. This means that every node with a side-effect has the
* function entry as its immediate dominator. So if node `x` dominates node
* `y` then there can be no side effects between `x` and `y` unless `x` is
* the function entry. So the optimal choice for `result` has the function
* entry as its immediate dominator.
*
* Example:
*
* ```
* 000: int f(int a, int b, int *p) {
* 001: int r = 0;
* 002: if (a) {
* 003: if (b) {
* 004: sideEffect1();
* 005: }
* 006: } else {
* 007: sideEffect2();
* 008: }
* 009: if (a) {
* 010: r++; // Not a side-effect, because r is an SSA variable.
* 011: }
* 012: if (b) {
* 013: r++; // Not a side-effect, because r is an SSA variable.
* 014: }
* 015: return *p;
* 016: }
* ```
*
* Suppose we want to find the most recent side-effect for the dereference
* of `p` on line 015. The `sideEffectCFG` has an edge from the function
* entry (line 000) to the side effects at lines 004 and 007. Therefore,
* the immediate dominator tree looks like this:
*
* 000 - 001 - 002 - 003
* - 004
* - 007
* - 009 - 010
* - 012 - 013
* - 015
*
* The immediate dominator path to line 015 is 000 - 009 - 012 - 015.
* Therefore, the most recent side effect for line 015 is line 009.
*/
cached
private ControlFlowNode mostRecentSideEffect(ControlFlowNode node) {
exists(ControlFlowNode entry |
functionEntry(entry) and
iDomEffect(entry, result) and
iDomEffect*(result, node)
)
}
/** Used to represent the "global value number" of an expression. */
cached
private newtype GvnBase =
GVN_IntConst(int val, Type t) { mk_IntConst(val, t, _) } or
GVN_FloatConst(float val, Type t) { mk_FloatConst(val, t, _) } or
// If the local variable does not have a defining value, then
// we use the SsaDefinition as its global value number.
GVN_UndefinedStackVariable(StackVariable x, SsaDefinition def) {
mk_UndefinedStackVariable(x, def, _)
} or
// Variables with no SSA information. As a crude (but safe)
// approximation, we use `mostRecentSideEffect` to compute a definition
// location for the variable. This ensures that two instances of the same
// global variable will only get the same value number if they are
// guaranteed to have the same value.
GVN_OtherVariable(Variable x, ControlFlowNode dominator) { mk_OtherVariable(x, dominator, _) } or
deprecated GVN_FieldAccess(GVN s, Field f) {
mk_DotFieldAccess(s, f, _) or
mk_PointerFieldAccess_with_deref(s, f, _) or
mk_ImplicitThisFieldAccess_with_deref(s, f, _)
} or
// Dereference a pointer. The value might have changed since the last
// time the pointer was dereferenced, so we need to include a definition
// location. As a crude (but safe) approximation, we use
// `mostRecentSideEffect` to compute a definition location.
deprecated GVN_Deref(GVN p, ControlFlowNode dominator) {
mk_Deref(p, dominator, _) or
mk_PointerFieldAccess(p, _, dominator, _) or
mk_ImplicitThisFieldAccess_with_qualifier(p, _, dominator, _)
} or
GVN_ThisExpr(Function fcn) {
mk_ThisExpr(fcn, _) or
mk_ImplicitThisFieldAccess(fcn, _, _, _)
} or
deprecated GVN_Conversion(Type t, GVN child) { mk_Conversion(t, child, _) } or
deprecated GVN_BinaryOp(GVN lhs, GVN rhs, string opname) { mk_BinaryOp(lhs, rhs, opname, _) } or
deprecated GVN_UnaryOp(GVN child, string opname) { mk_UnaryOp(child, opname, _) } or
deprecated GVN_ArrayAccess(GVN x, GVN i, ControlFlowNode dominator) {
mk_ArrayAccess(x, i, dominator, _)
} or
// Any expression that is not handled by the cases above is
// given a unique number based on the expression itself.
GVN_Unanalyzable(Expr e) { not analyzableExpr(e) }
/**
* A Global Value Number. A GVN is an abstract representation of the value
* computed by an expression. The relationship between `Expr` and `GVN` is
* many-to-one: every `Expr` has exactly one `GVN`, but multiple
* expressions can have the same `GVN`. If two expressions have the same
* `GVN`, it means that they compute the same value at run time. The `GVN`
* is an opaque value, so you cannot deduce what the run-time value of an
* expression will be from its `GVN`. The only use for the `GVN` of an
* expression is to find other expressions that compute the same value.
* Use the predicate `globalValueNumber` to get the `GVN` for an `Expr`.
*
* Note: `GVN` has `toString` and `getLocation` methods, so that it can be
* displayed in a results list. These work by picking an arbitrary
* expression with this `GVN` and using its `toString` and `getLocation`
* methods.
*/
deprecated class GVN extends GvnBase {
GVN() { this instanceof GvnBase }
/** Gets an expression that has this GVN. */
Expr getAnExpr() { this = globalValueNumber(result) }
/** Gets the kind of the GVN. This can be useful for debugging. */
string getKind() {
if this instanceof GVN_IntConst
then result = "IntConst"
else
if this instanceof GVN_FloatConst
then result = "FloatConst"
else
if this instanceof GVN_UndefinedStackVariable
then result = "UndefinedStackVariable"
else
if this instanceof GVN_OtherVariable
then result = "OtherVariable"
else
if this instanceof GVN_FieldAccess
then result = "FieldAccess"
else
if this instanceof GVN_Deref
then result = "Deref"
else
if this instanceof GVN_ThisExpr
then result = "ThisExpr"
else
if this instanceof GVN_Conversion
then result = "Conversion"
else
if this instanceof GVN_BinaryOp
then result = "BinaryOp"
else
if this instanceof GVN_UnaryOp
then result = "UnaryOp"
else
if this instanceof GVN_ArrayAccess
then result = "ArrayAccess"
else
if this instanceof GVN_Unanalyzable
then result = "Unanalyzable"
else result = "error"
}
/**
* Gets an example of an expression with this GVN.
* This is useful for things like implementing toString().
*/
private Expr exampleExpr() {
// Pick the expression with the minimum source location string. This is
// just an arbitrary way to pick an expression with this `GVN`.
result = min(Expr e | this = globalValueNumber(e) | e order by e.getLocation().toString())
}
/** Gets a textual representation of this element. */
string toString() { result = this.exampleExpr().toString() }
/** Gets the primary location of this element. */
Location getLocation() { result = this.exampleExpr().getLocation() }
}
private predicate analyzableIntConst(Expr e) {
strictcount(e.getValue().toInt()) = 1 and
strictcount(e.getUnspecifiedType()) = 1
}
private predicate mk_IntConst(int val, Type t, Expr e) {
analyzableIntConst(e) and
val = e.getValue().toInt() and
t = e.getUnspecifiedType()
}
private predicate analyzableFloatConst(Expr e) {
strictcount(e.getValue().toFloat()) = 1 and
strictcount(e.getUnspecifiedType()) = 1 and
not analyzableIntConst(e)
}
private predicate mk_FloatConst(float val, Type t, Expr e) {
analyzableFloatConst(e) and
val = e.getValue().toFloat() and
t = e.getUnspecifiedType()
}
private predicate analyzableStackVariable(VariableAccess access) {
strictcount(SsaDefinition def | def.getAUse(_) = access | def) = 1 and
strictcount(SsaDefinition def, Variable v | def.getAUse(v) = access | v) = 1 and
count(SsaDefinition def, Variable v |
def.getAUse(v) = access
|
def.getDefiningValue(v).getFullyConverted()
) <= 1 and
not analyzableConst(access)
}
// Note: this predicate only has a result if the access has no
// defining value. If there is a defining value, then there is no
// need to generate a fresh `GVN` for the access because `globalValueNumber`
// will follow the chain and use the GVN of the defining value.
private predicate mk_UndefinedStackVariable(
StackVariable x, SsaDefinition def, VariableAccess access
) {
analyzableStackVariable(access) and
access = def.getAUse(x) and
not exists(def.getDefiningValue(x))
}
private predicate analyzableDotFieldAccess(DotFieldAccess access) {
strictcount(access.getTarget()) = 1 and
strictcount(access.getQualifier().getFullyConverted()) = 1 and
not analyzableConst(access)
}
deprecated private predicate mk_DotFieldAccess(GVN qualifier, Field target, DotFieldAccess access) {
analyzableDotFieldAccess(access) and
target = access.getTarget() and
qualifier = globalValueNumber(access.getQualifier().getFullyConverted())
}
private predicate analyzablePointerFieldAccess(PointerFieldAccess access) {
strictcount(mostRecentSideEffect(access)) = 1 and
strictcount(access.getTarget()) = 1 and
strictcount(access.getQualifier().getFullyConverted()) = 1 and
not analyzableConst(access)
}
deprecated private predicate mk_PointerFieldAccess(
GVN qualifier, Field target, ControlFlowNode dominator, PointerFieldAccess access
) {
analyzablePointerFieldAccess(access) and
dominator = mostRecentSideEffect(access) and
target = access.getTarget() and
qualifier = globalValueNumber(access.getQualifier().getFullyConverted())
}
/**
* `obj->field` is equivalent to `(*obj).field`, so we need to wrap an
* extra `GVN_Deref` around the qualifier.
*/
deprecated private predicate mk_PointerFieldAccess_with_deref(
GVN new_qualifier, Field target, PointerFieldAccess access
) {
exists(GVN qualifier, ControlFlowNode dominator |
mk_PointerFieldAccess(qualifier, target, dominator, access) and
new_qualifier = GVN_Deref(qualifier, dominator)
)
}
private predicate analyzableImplicitThisFieldAccess(ImplicitThisFieldAccess access) {
strictcount(mostRecentSideEffect(access)) = 1 and
strictcount(access.getTarget()) = 1 and
strictcount(access.getEnclosingFunction()) = 1 and
not analyzableConst(access)
}
private predicate mk_ImplicitThisFieldAccess(
Function fcn, Field target, ControlFlowNode dominator, ImplicitThisFieldAccess access
) {
analyzableImplicitThisFieldAccess(access) and
dominator = mostRecentSideEffect(access) and
target = access.getTarget() and
fcn = access.getEnclosingFunction()
}
deprecated private predicate mk_ImplicitThisFieldAccess_with_qualifier(
GVN qualifier, Field target, ControlFlowNode dominator, ImplicitThisFieldAccess access
) {
exists(Function fcn |
mk_ImplicitThisFieldAccess(fcn, target, dominator, access) and
qualifier = GVN_ThisExpr(fcn)
)
}
deprecated private predicate mk_ImplicitThisFieldAccess_with_deref(
GVN new_qualifier, Field target, ImplicitThisFieldAccess access
) {
exists(GVN qualifier, ControlFlowNode dominator |
mk_ImplicitThisFieldAccess_with_qualifier(qualifier, target, dominator, access) and
new_qualifier = GVN_Deref(qualifier, dominator)
)
}
/**
* Holds if `access` is an access of a variable that does
* not have SSA information. (For example, because the variable
* is global.)
*/
private predicate analyzableOtherVariable(VariableAccess access) {
not access instanceof FieldAccess and
not exists(SsaDefinition def | access = def.getAUse(_)) and
strictcount(access.getTarget()) = 1 and
strictcount(mostRecentSideEffect(access)) = 1 and
not analyzableConst(access)
}
private predicate mk_OtherVariable(Variable x, ControlFlowNode dominator, VariableAccess access) {
analyzableOtherVariable(access) and
x = access.getTarget() and
dominator = mostRecentSideEffect(access)
}
private predicate analyzableConversion(Conversion conv) {
strictcount(conv.getUnspecifiedType()) = 1 and
strictcount(conv.getExpr()) = 1 and
not analyzableConst(conv)
}
deprecated private predicate mk_Conversion(Type t, GVN child, Conversion conv) {
analyzableConversion(conv) and
t = conv.getUnspecifiedType() and
child = globalValueNumber(conv.getExpr())
}
private predicate analyzableBinaryOp(BinaryOperation op) {
op.isPure() and
strictcount(op.getLeftOperand().getFullyConverted()) = 1 and
strictcount(op.getRightOperand().getFullyConverted()) = 1 and
strictcount(op.getOperator()) = 1 and
not analyzableConst(op)
}
deprecated private predicate mk_BinaryOp(GVN lhs, GVN rhs, string opname, BinaryOperation op) {
analyzableBinaryOp(op) and
lhs = globalValueNumber(op.getLeftOperand().getFullyConverted()) and
rhs = globalValueNumber(op.getRightOperand().getFullyConverted()) and
opname = op.getOperator()
}
private predicate analyzableUnaryOp(UnaryOperation op) {
not op instanceof PointerDereferenceExpr and
op.isPure() and
strictcount(op.getOperand().getFullyConverted()) = 1 and
strictcount(op.getOperator()) = 1 and
not analyzableConst(op)
}
deprecated private predicate mk_UnaryOp(GVN child, string opname, UnaryOperation op) {
analyzableUnaryOp(op) and
child = globalValueNumber(op.getOperand().getFullyConverted()) and
opname = op.getOperator()
}
private predicate analyzableThisExpr(ThisExpr thisExpr) {
strictcount(thisExpr.getEnclosingFunction()) = 1 and
not analyzableConst(thisExpr)
}
private predicate mk_ThisExpr(Function fcn, ThisExpr thisExpr) {
analyzableThisExpr(thisExpr) and
fcn = thisExpr.getEnclosingFunction()
}
private predicate analyzableArrayAccess(ArrayExpr ae) {
strictcount(ae.getArrayBase().getFullyConverted()) = 1 and
strictcount(ae.getArrayOffset().getFullyConverted()) = 1 and
strictcount(mostRecentSideEffect(ae)) = 1 and
not analyzableConst(ae)
}
deprecated private predicate mk_ArrayAccess(
GVN base, GVN offset, ControlFlowNode dominator, ArrayExpr ae
) {
analyzableArrayAccess(ae) and
base = globalValueNumber(ae.getArrayBase().getFullyConverted()) and
offset = globalValueNumber(ae.getArrayOffset().getFullyConverted()) and
dominator = mostRecentSideEffect(ae)
}
private predicate analyzablePointerDereferenceExpr(PointerDereferenceExpr deref) {
strictcount(deref.getOperand().getFullyConverted()) = 1 and
strictcount(mostRecentSideEffect(deref)) = 1 and
not analyzableConst(deref)
}
deprecated private predicate mk_Deref(GVN p, ControlFlowNode dominator, PointerDereferenceExpr deref) {
analyzablePointerDereferenceExpr(deref) and
p = globalValueNumber(deref.getOperand().getFullyConverted()) and
dominator = mostRecentSideEffect(deref)
}
/** Gets the global value number of expression `e`. */
cached
deprecated GVN globalValueNumber(Expr e) {
exists(int val, Type t |
mk_IntConst(val, t, e) and
result = GVN_IntConst(val, t)
)
or
exists(float val, Type t |
mk_FloatConst(val, t, e) and
result = GVN_FloatConst(val, t)
)
or
// Local variable with a defining value.
exists(StackVariable x, SsaDefinition def |
analyzableStackVariable(e) and
e = def.getAUse(x) and
result = globalValueNumber(def.getDefiningValue(x).getFullyConverted())
)
or
// Local variable without a defining value.
exists(StackVariable x, SsaDefinition def |
mk_UndefinedStackVariable(x, def, e) and
result = GVN_UndefinedStackVariable(x, def)
)
or
// Variable with no SSA information.
exists(Variable x, ControlFlowNode dominator |
mk_OtherVariable(x, dominator, e) and
result = GVN_OtherVariable(x, dominator)
)
or
exists(GVN qualifier, Field target |
mk_DotFieldAccess(qualifier, target, e) and
result = GVN_FieldAccess(qualifier, target)
)
or
exists(GVN qualifier, Field target |
mk_PointerFieldAccess_with_deref(qualifier, target, e) and
result = GVN_FieldAccess(qualifier, target)
)
or
exists(GVN qualifier, Field target |
mk_ImplicitThisFieldAccess_with_deref(qualifier, target, e) and
result = GVN_FieldAccess(qualifier, target)
)
or
exists(Function fcn |
mk_ThisExpr(fcn, e) and
result = GVN_ThisExpr(fcn)
)
or
exists(Type t, GVN child |
mk_Conversion(t, child, e) and
result = GVN_Conversion(t, child)
)
or
exists(GVN lhs, GVN rhs, string opname |
mk_BinaryOp(lhs, rhs, opname, e) and
result = GVN_BinaryOp(lhs, rhs, opname)
)
or
exists(GVN child, string opname |
mk_UnaryOp(child, opname, e) and
result = GVN_UnaryOp(child, opname)
)
or
exists(GVN x, GVN i, ControlFlowNode dominator |
mk_ArrayAccess(x, i, dominator, e) and
result = GVN_ArrayAccess(x, i, dominator)
)
or
exists(GVN p, ControlFlowNode dominator |
mk_Deref(p, dominator, e) and
result = GVN_Deref(p, dominator)
)
or
not analyzableExpr(e) and result = GVN_Unanalyzable(e)
}
private predicate analyzableConst(Expr e) {
analyzableIntConst(e) or
analyzableFloatConst(e)
}
/**
* Holds if the expression is explicitly handled by `globalValueNumber`.
* Unanalyzable expressions still need to be given a global value number,
* but it will be a unique number that is not shared with any other
* expression.
*/
private predicate analyzableExpr(Expr e) {
analyzableConst(e) or
analyzableStackVariable(e) or
analyzableDotFieldAccess(e) or
analyzablePointerFieldAccess(e) or
analyzableImplicitThisFieldAccess(e) or
analyzableOtherVariable(e) or
analyzableConversion(e) or
analyzableBinaryOp(e) or
analyzableUnaryOp(e) or
analyzableThisExpr(e) or
analyzableArrayAccess(e) or
analyzablePointerDereferenceExpr(e)
}

View File

@@ -1,3 +1,11 @@
## 0.9.11
### Minor Analysis Improvements
* The "Uncontrolled data used in path expression" query (`cpp/path-injection`) query produces fewer near-duplicate results.
* The "Global variable may be used before initialization" query (`cpp/global-use-before-init`) no longer raises an alert on global variables that are initialized when they are declared.
* The "Inconsistent null check of pointer" query (`cpp/inconsistent-nullness-testing`) query no longer raises an alert when the guarded check is in a macro expansion.
## 0.9.10
No user-facing changes.

View File

@@ -22,10 +22,8 @@ function.
</example>
<references>
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
<li>CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO47-C.+Use+valid+format+strings">FIO47-C. Use valid format strings</a>.</li>
<li>Microsoft C Runtime Library Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, wprintf</a>.</li>
</references>
</qhelp>

View File

@@ -19,8 +19,8 @@ contents.
</overview>
<recommendation>
<p>Review the format and arguments expected by the highlighted function calls. Update either
the format or the arguments so that the expected number of arguments are passed to the
<p>Review the format and arguments expected by the highlighted function calls. Update either
the format or the arguments so that the expected number of arguments are passed to the
function.
</p>
@@ -30,11 +30,8 @@ function.
</example>
<references>
<li>CERT C Coding
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude user input from format strings</a>.</li>
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
<li>CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO47-C.+Use+valid+format+strings">FIO47-C. Use valid format strings</a>.</li>
<li>Microsoft C Runtime Library Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, wprintf</a>.</li>
</references>
</qhelp>

View File

@@ -1,4 +0,0 @@
int main() {
printf("%s\n", 42); //printf will treat 42 as a char*, will most likely segfault
return 0;
}

View File

@@ -4,29 +4,33 @@
<qhelp>
<overview>
<p>Each call to the <code>printf</code> function or a related function should include
the type and sequence of arguments defined by the format. If the function is passed arguments
the type and sequence of arguments defined by the format. If the function is passed arguments
of a different type or in a different sequence then the arguments are reinterpreted to fit the type and sequence expected, resulting in unpredictable behavior.</p>
</overview>
<recommendation>
<p>Review the format and arguments expected by the highlighted function calls. Update either
the format or the arguments so that the expected type and sequence of arguments are passed to
<p>Review the format and arguments expected by the highlighted function calls. Update either
the format or the arguments so that the expected type and sequence of arguments are passed to
the function.
</p>
</recommendation>
<example><sample src="WrongTypeFormatArguments.cpp" />
<example>
<p>In the following example, the wrong format specifier is given for an integer format argument:</p>
<sample src="WrongTypeFormatArgumentsBad.cpp" />
<p>The corrected version uses <code>%i</code> as the format specifier for the integer format argument:</p>
<sample src="WrongTypeFormatArgumentsGood.cpp" />
</example>
<references>
<li>CERT C Coding
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude user input from format strings</a>.</li>
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
<li>CRT Alphabetical Function Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, _printf_l, wprintf, _wprintf_l</a>.</li>
<li>Microsoft Learn: <a href="https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170">Format specification syntax: printf and wprintf functions</a>.</li>
<li>cplusplus.com:<a href="https://cplusplus.com/reference/cstdio/printf/"></a>printf</li>
<li>CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO47-C.+Use+valid+format+strings">FIO47-C. Use valid format strings</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,4 @@
int main() {
printf("%s\n", 42); // BAD: printf will treat 42 as a char*, will most likely segfault
return 0;
}

View File

@@ -0,0 +1,4 @@
int main() {
printf("%i\n", 42); // GOOD: printf will treat 42 as an int
return 0;
}

View File

@@ -2,19 +2,18 @@
void f_warning(int i)
{
// The usage of the logical not operator in this case is unlikely to be correct
// BAD: the usage of the logical not operator in this case is unlikely to be correct
// as the output is being used as an operator for a bit-wise and operation
if (i & !FLAGS)
if (i & !FLAGS)
{
// code
}
}
void f_fixed(int i)
{
if (i & ~FLAGS) // Changing the logical not operator for the bit-wise not operator would fix this logic
if (i & ~FLAGS) // GOOD: Changing the logical not operator for the bit-wise not operator would fix this logic
{
// code
}
}
}

View File

@@ -16,7 +16,13 @@
<p>Carefully inspect the flagged expressions. Consider the intent in the code logic, and decide whether it is necessary to change the not operator.</p>
</recommendation>
<example><sample src="IncorrectNotOperatorUsage.cpp" /></example>
<example>
<p>Here is an example of this issue and how it can be fixed:</p>
<sample src="IncorrectNotOperatorUsage.cpp" />
<p>In other cases, particularly when the expressions have <code>bool</code> type, the fix may instead be of the form <code>a &amp;&amp; !b</code>.</p>
</example>
<references>
<li>

View File

@@ -1,2 +0,0 @@
strncpy(dest, src, sizeof(src)); //wrong: size of dest should be used
strncpy(dest, src, strlen(src)); //wrong: size of dest should be used

View File

@@ -3,7 +3,7 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>The standard library function <code>strncpy</code> copies a source string to a destination buffer. The third argument defines the maximum number of characters to copy and should be less than
<p>The standard library function <code>strncpy</code> copies a source string to a destination buffer. The third argument defines the maximum number of characters to copy and should be less than
or equal to the size of the destination buffer. Calls of the form <code>strncpy(dest, src, strlen(src))</code> or <code>strncpy(dest, src, sizeof(src))</code> incorrectly set the third argument to the size of the source buffer. Executing a call of this type may cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability.</p>
</overview>
@@ -12,14 +12,20 @@ or equal to the size of the destination buffer. Calls of the form <code>strncpy(
not the source buffer.</p>
</recommendation>
<example><sample src="StrncpyFlippedArgs.cpp" />
<example>
<p>In the following examples, the size of the source buffer is incorrectly used as a parameter to <code>strncpy</code>:</p>
<sample src="StrncpyFlippedArgsBad.cpp" />
<p>The corrected version uses the size of the destination buffer, or a variable containing the size of the destination buffer as the size parameter to <code>strncpy</code>:</p>
<sample src="StrncpyFlippedArgsGood.cpp" />
</example>
<references>
<li>cplusplus.com: <a href="http://www.cplusplus.com/reference/clibrary/cstring/strncpy/">strncpy</a>.</li>
<li>cplusplus.com: <a href="https://cplusplus.com/reference/cstring/strncpy/">strncpy</a>.</li>
<li>
I. Gerg. <em>An Overview and Example of the Buffer-Overflow Exploit</em>. IANewsletter vol 7 no 4. 2005.
</li>

View File

@@ -0,0 +1,9 @@
char src[256];
char dest1[128];
...
strncpy(dest1, src, sizeof(src)); // wrong: size of dest should be used
char *dest2 = (char *)malloc(sz1 + sz2 + sz3);
strncpy(dest2, src, strlen(src)); // wrong: size of dest should be used

View File

@@ -0,0 +1,10 @@
char src[256];
char dest1[128];
...
strncpy(dest1, src, sizeof(dest1)); // correct
size_t destSize = sz1 + sz2 + sz3;
char *dest2 = (char *)malloc(destSize);
strncpy(dest2, src, destSize); // correct

View File

@@ -88,6 +88,11 @@ module TaintedPathConfig implements DataFlow::ConfigSig {
hasUpperBoundsCheck(checkedVar)
)
}
predicate isBarrierOut(DataFlow::Node node) {
// make sinks barriers so that we only report the closest instance
isSink(node)
}
}
module TaintedPath = TaintTracking::Global<TaintedPathConfig>;

View File

@@ -30,6 +30,12 @@ This is because the temporary container is not bound to a rvalue reference.
</p>
<sample src="IteratorToExpiredContainerExtendedLifetime.cpp" />
<p>
To fix <code>lifetime_of_temp_not_extended</code>, consider rewriting the code so that the lifetime of the temporary object is extended.
In <code>fixed_lifetime_of_temp_not_extended</code>, the lifetime of the temporary object has been extended by storing it in an rvalue reference.
</p>
<sample src="IteratorToExpiredContainerExtendedLifetime-fixed.cpp" />
</example>
<references>

View File

@@ -2,9 +2,10 @@
* @name Iterator to expired container
* @description Using an iterator owned by a container whose lifetime has expired may lead to unexpected behavior.
* @kind problem
* @precision high
* @precision medium
* @id cpp/iterator-to-expired-container
* @problem.severity warning
* @security-severity 8.8
* @tags reliability
* security
* external/cwe/cwe-416
@@ -61,14 +62,38 @@ DataFlow::Node getADestroyedNode(DataFlow::Node n) {
)
}
predicate destroyedToBeginSink(DataFlow::Node sink, FunctionCall fc) {
predicate destroyedToBeginSink(DataFlow::Node sink) {
exists(CallInstruction call |
call = sink.asOperand().(ThisArgumentOperand).getCall() and
fc = call.getUnconvertedResultExpression() and
call.getStaticCallTarget() instanceof BeginOrEndFunction
)
}
/**
* Holds if `node1` is the node corresponding to a qualifier of a destructor
* call and `node2` is a node that is destroyed as a result of `node1` being
* destroyed.
*/
private predicate qualifierToDestroyed(DataFlow::Node node1, DataFlow::Node node2) {
tempToDestructorSink(node1, _) and
node2 = getADestroyedNode(node1)
}
/**
* A configuration to track flow from a destroyed node to a qualifier of
* a `begin` or `end` function call.
*
* This configuration exists to prevent a cartesian product between all sinks and
* all states in `Config::isSink`.
*/
module Config0 implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { qualifierToDestroyed(_, source) }
predicate isSink(DataFlow::Node sink) { destroyedToBeginSink(sink) }
}
module Flow0 = DataFlow::Global<Config0>;
/**
* A configuration to track flow from a temporary variable to the qualifier of
* a destructor call, and subsequently to a qualifier of a call to `begin` or
@@ -78,12 +103,15 @@ module Config implements DataFlow::StateConfigSig {
newtype FlowState =
additional TempToDestructor() or
additional DestroyedToBegin(DataFlow::Node n) {
exists(DataFlow::Node thisOperand |
tempToDestructorSink(thisOperand, _) and
n = getADestroyedNode(thisOperand)
)
any(Flow0::PathNode pn | pn.isSource()).getNode() = n
}
/**
* Holds if `sink` is a qualifier to a call to `begin`, and `mid` is an
* object that is destroyed.
*/
private predicate relevant(DataFlow::Node mid, DataFlow::Node sink) { Flow0::flow(mid, sink) }
predicate isSource(DataFlow::Node source, FlowState state) {
source.asInstruction().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable and
state = TempToDestructor()
@@ -92,16 +120,16 @@ module Config implements DataFlow::StateConfigSig {
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
tempToDestructorSink(node1, _) and
state1 = TempToDestructor() and
state2 = DestroyedToBegin(node2) and
node2 = getADestroyedNode(node1)
qualifierToDestroyed(node1, node2)
}
predicate isSink(DataFlow::Node sink, FlowState state) {
// Note: This is a non-trivial cartesian product!
// Hopefully, both of these sets are quite small in practice
destroyedToBeginSink(sink, _) and state instanceof DestroyedToBegin
exists(DataFlow::Node mid |
relevant(mid, sink) and
state = DestroyedToBegin(mid)
)
}
DataFlow::FlowFeature getAFeature() {
@@ -121,9 +149,9 @@ module Config implements DataFlow::StateConfigSig {
module Flow = DataFlow::GlobalWithState<Config>;
from Flow::PathNode source, Flow::PathNode sink, FunctionCall beginOrEnd, DataFlow::Node mid
from Flow::PathNode source, Flow::PathNode sink, DataFlow::Node mid
where
Flow::flowPath(source, sink) and
destroyedToBeginSink(sink.getNode(), beginOrEnd) and
destroyedToBeginSink(sink.getNode()) and
sink.getState() = Config::DestroyedToBegin(mid)
select mid, "This object is destroyed before $@ is called.", beginOrEnd, beginOrEnd.toString()
select mid, "This object is destroyed at the end of the full-expression."

View File

@@ -0,0 +1,6 @@
void fixed_lifetime_of_temp_not_extended() {
auto&& v = get_vector();
for(auto x : log_and_return_argument(v)) {
use(x); // GOOD: The lifetime of the container returned by `get_vector()` has been extended to the lifetime of `v`.
}
}

View File

@@ -8,6 +8,12 @@
When the <code>std::string</code> object is destroyed, the pointer returned by <code>c_str</code> is no
longer valid. If the pointer is used after the <code>std::string</code> object is destroyed, then the behavior is undefined.
</p>
<p>Typically, this problem occurs when a <code>std::string</code> is returned by a function call (or overloaded operator)
by value, and the result is not immediately stored in a variable by value or reference in a way that extends the lifetime of
the temporary object. The resulting temporary <code>std::string</code> object is destroyed at the end of the containing expression
statement, along with any memory returned by a call to <code>c_str</code>.
</p>
</overview>
<recommendation>
@@ -39,6 +45,8 @@ points to valid memory.
<references>
<li><a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM50-CPP.+Do+not+access+freed+memory">MEM50-CPP. Do not access freed memory</a>.</li>
<li>Microsoft Learn: <a href="https://learn.microsoft.com/en-us/cpp/cpp/temporary-objects?view=msvc-170">Temporary objects</a>.</li>
<li>cppreference.com: <a href="https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary">Lifetime of a temporary</a>.</li>
</references>
</qhelp>

View File

@@ -23,4 +23,5 @@ where
(c.getTarget() instanceof StdStringCStr or c.getTarget() instanceof StdStringData) and
isTemporary(c.getQualifier().getFullyConverted())
select c,
"The underlying string object is destroyed after the call to '" + c.getTarget() + "' returns."
"The underlying temporary string object is destroyed after the call to '" + c.getTarget() +
"' returns."

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query, `cpp/iterator-to-expired-container`, to detect the creation of iterators owned by a temporary objects that are about to be destroyed.

View File

@@ -1,5 +1,7 @@
---
category: minorAnalysis
---
## 0.9.11
### Minor Analysis Improvements
* The "Uncontrolled data used in path expression" query (`cpp/path-injection`) query produces fewer near-duplicate results.
* The "Global variable may be used before initialization" query (`cpp/global-use-before-init`) no longer raises an alert on global variables that are initialized when they are declared.
* The "Inconsistent null check of pointer" query (`cpp/inconsistent-nullness-testing`) query no longer raises an alert when the guarded check is in a macro expansion.
* The "Inconsistent null check of pointer" query (`cpp/inconsistent-nullness-testing`) query no longer raises an alert when the guarded check is in a macro expansion.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.9.10
lastReleaseVersion: 0.9.11

View File

@@ -0,0 +1,11 @@
void test()
{
char *foo = malloc(100);
// BAD
if (foo)
free(foo);
// GOOD
free(foo);
}

View File

@@ -0,0 +1,18 @@
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
<qhelp>
<overview>
<p>The <code>free</code> function, which deallocates heap memory, may accept a NULL pointer and take no action. Therefore, it is unnecessary to check its argument for the value of NULL before a function call to <code>free</code>. As such, these guards may hinder performance and readability.</p>
</overview>
<recommendation>
<p>A function call to <code>free</code> should not depend upon the value of its argument. Delete the <code>if</code> condition preceeding a function call to <code>free</code> when its only purpose is to check the value of the pointer to be freed.</p>
</recommendation>
<example>
<sample src = "GuardedFree.cpp" />
</example>
<references>
<li>
The Open Group Base Specifications Issue 7, 2018 Edition:
<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html">free - free allocated memory</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,26 @@
/**
* @name Guarded Free
* @description NULL-condition guards before function calls to the memory-deallocation
* function free(3) are unnecessary, because passing NULL to free(3) is a no-op.
* @kind problem
* @problem.severity recommendation
* @precision very-high
* @id cpp/guarded-free
* @tags maintainability
* readability
* experimental
*/
import cpp
import semmle.code.cpp.controlflow.Guards
class FreeCall extends FunctionCall {
FreeCall() { this.getTarget().hasGlobalName("free") }
}
from GuardCondition gc, FreeCall fc, Variable v, BasicBlock bb
where
gc.ensuresEq(v.getAnAccess(), 0, bb, false) and
fc.getArgument(0) = v.getAnAccess() and
bb = fc.getEnclosingStmt()
select gc, "unnecessary NULL check before call to $@", fc, "free"

View File

@@ -24,7 +24,7 @@ predicate exprMayBeString(Expr exp) {
fctmp.getAnArgument().(VariableAccess).getTarget() = exp.(VariableAccess).getTarget() or
globalValueNumber(fctmp.getAnArgument()) = globalValueNumber(exp)
) and
fctmp.getTarget().hasName(["strlen", "strcat", "strncat", "strcpy", "sptintf", "printf"])
fctmp.getTarget().hasName(["strlen", "strcat", "strncat", "strcpy", "sprintf", "printf"])
)
or
exists(AssignExpr astmp |

View File

@@ -1,20 +0,0 @@
import cpp
class StringVariable extends Variable {
StringVariable() {
this.getType().(PointerType).stripType().getName() = "char"
}
}
class StringField extends StringVariable, Field
{
}
class StringParameter extends StringVariable, Parameter
{
}
from StringVariable f
where f.getFile().getRelativePath().matches("c/extractor/src/%")
and not f.getASpecifier().getName() = "extern"
select f, f.getFile().getRelativePath()

View File

@@ -1,9 +0,0 @@
import cpp
import relevant
from Function fn
where
fn.getNamespace() instanceof GlobalNamespace and
not exists(fn.getDeclaringType()) and
is_relevant_result(fn.getFile())
select fn, "This function is not declared in a namespace", fn.getFile().getRelativePath()

View File

@@ -1,4 +0,0 @@
import cpp
from Function fn
where not exists(fn.getDeclaringType()) and is_relevant_result(fn.getFile())

View File

@@ -1,25 +0,0 @@
// Flags use of global variables
import cpp
class RelevantGlobalVariable extends GlobalVariable
{
RelevantGlobalVariable() {
any()
}
}
predicate is_valid_global_variable(Variable var) {
var.getType().stripType().getName() = "trie_node" or
var.getType().isConst() or
var.getType().isDeeplyConst() or
var.isConstexpr() or
var.getType() instanceof ArrayType or
var.getASpecifier().getName() = "extern" or
var.getFile().getRelativePath().matches("c/extractor/edg/%")
}
from GlobalVariable globalVariable, string typeName
where
not is_valid_global_variable(globalVariable) and
typeName = globalVariable.getType().stripType().getName()
select globalVariable, typeName, globalVariable.getFile().getRelativePath()

View File

@@ -1,7 +0,0 @@
import cpp
import relevant
from Call call
where call.getTarget().getName().matches("%printf")
and is_relevant_result(call.getFile())
select call, "Call to a printf formatter", call.getFile().getRelativePath()

View File

@@ -1,6 +0,0 @@
import cpp
predicate is_relevant_result(File file)
{
not file.getRelativePath().matches("c/extractor/edg%")
}

View File

@@ -1,25 +0,0 @@
import cpp
class ACompressedFileWrite extends Function {
ACompressedFileWrite() {
this.getName() = "operator<<" and
this.getParameter(0).getType().stripType().getName() = "a_compressed_file"
}
}
class LabelDefinition extends Call {
LabelDefinition() {
this.getTarget() instanceof ACompressedFileWrite and
this.getArgument(1).(StringLiteral).getValue().matches("=%")
}
}
predicate is_valid_file_write(Call call) {
call.getFile().getBaseName() = "dbscheme.cpp"
}
from Call call
where
call.getTarget() instanceof ACompressedFileWrite
and not is_valid_file_write(call)
select call

View File

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

View File

@@ -1,11 +0,0 @@
| test.cpp:680:30:680:30 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:680:17:680:17 | call to begin | call to begin |
| test.cpp:680:30:680:30 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:680:17:680:17 | call to end | call to end |
| test.cpp:683:31:683:32 | call to at | This object is destroyed before $@ is called. | test.cpp:683:17:683:17 | call to begin | call to begin |
| test.cpp:683:31:683:32 | call to at | This object is destroyed before $@ is called. | test.cpp:683:17:683:17 | call to end | call to end |
| test.cpp:689:46:689:58 | pointer to ~vector output argument | This object is destroyed before $@ is called. | test.cpp:689:60:689:62 | call to end | call to end |
| test.cpp:702:27:702:27 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:703:19:703:23 | call to begin | call to begin |
| test.cpp:702:27:702:27 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:703:36:703:38 | call to end | call to end |
| test.cpp:727:23:727:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:750:17:750:17 | call to begin | call to begin |
| test.cpp:727:23:727:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:750:17:750:17 | call to end | call to end |
| test.cpp:735:23:735:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:759:17:759:17 | call to begin | call to begin |
| test.cpp:735:23:735:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:759:17:759:17 | call to end | call to end |

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql

View File

@@ -56,6 +56,8 @@ astGuardsCompare
| 17 | y < 1+1 when ... > ... is false |
| 17 | y >= 1+1 when ... && ... is true |
| 17 | y >= 1+1 when ... > ... is true |
| 18 | call to get != 0 when call to get is true |
| 18 | call to get == 0 when call to get is false |
| 26 | 0 < x+0 when ... > ... is true |
| 26 | 0 >= x+0 when ... > ... is false |
| 26 | x < 0+1 when ... > ... is false |
@@ -146,6 +148,24 @@ astGuardsCompare
| 109 | y < 0+0 when ... < ... is true |
| 109 | y >= 0+0 when ... < ... is false |
| 109 | y >= 0+0 when ... \|\| ... is false |
| 126 | 1 != 0 when 1 is true |
| 126 | 1 != 0 when ... && ... is true |
| 126 | 1 == 0 when 1 is false |
| 126 | call to test3_condition != 0 when ... && ... is true |
| 126 | call to test3_condition != 0 when call to test3_condition is true |
| 126 | call to test3_condition == 0 when call to test3_condition is false |
| 131 | b != 0 when b is true |
| 131 | b == 0 when b is false |
| 137 | 0 != 0 when 0 is true |
| 137 | 0 == 0 when 0 is false |
| 146 | ! ... != 0 when ! ... is true |
| 146 | ! ... == 0 when ! ... is false |
| 152 | x != 0 when ... && ... is true |
| 152 | x != 0 when x is true |
| 152 | x == 0 when x is false |
| 152 | y != 0 when ... && ... is true |
| 152 | y != 0 when y is true |
| 152 | y == 0 when y is false |
| 156 | ... + ... != x+0 when ... == ... is false |
| 156 | ... + ... == x+0 when ... == ... is true |
| 156 | x != ... + ...+0 when ... == ... is false |
@@ -184,6 +204,8 @@ astGuardsCompare
| 175 | call to foo != 0+0 when ... == ... is false |
| 175 | call to foo == 0 when ... == ... is true |
| 175 | call to foo == 0+0 when ... == ... is true |
| 181 | x != 0 when x is true |
| 181 | x == 0 when x is false |
astGuardsControl
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
@@ -485,8 +507,28 @@ astGuardsEnsure_const
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 126 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
| test.c:131:7:131:7 | b | test.c:131:7:131:7 | b | != | 0 | 131 | 132 |
| test.c:137:7:137:7 | 0 | test.c:137:7:137:7 | 0 | == | 0 | 142 | 136 |
| test.c:146:7:146:8 | ! ... | test.c:146:7:146:8 | ! ... | != | 0 | 146 | 147 |
| test.c:152:10:152:10 | x | test.c:152:10:152:10 | x | != | 0 | 151 | 152 |
| test.c:152:10:152:10 | x | test.c:152:10:152:10 | x | != | 0 | 152 | 152 |
| test.c:152:10:152:15 | ... && ... | test.c:152:10:152:10 | x | != | 0 | 151 | 152 |
| test.c:152:10:152:15 | ... && ... | test.c:152:15:152:15 | y | != | 0 | 151 | 152 |
| test.c:152:15:152:15 | y | test.c:152:15:152:15 | y | != | 0 | 151 | 152 |
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | != | 0 | 175 | 175 |
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | == | 0 | 175 | 175 |
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | != | 0 | 181 | 182 |
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | != | 0 | 186 | 180 |
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | == | 0 | 183 | 184 |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
@@ -545,6 +587,8 @@ irGuardsCompare
| 17 | y < 2 when CompareGT: ... > ... is false |
| 17 | y >= 1+1 when CompareGT: ... > ... is true |
| 17 | y >= 2 when CompareGT: ... > ... is true |
| 18 | call to get != 0 when CompareNE: (bool)... is true |
| 18 | call to get == 0 when CompareNE: (bool)... is false |
| 26 | 0 < x+0 when CompareGT: ... > ... is true |
| 26 | 0 >= x+0 when CompareGT: ... > ... is false |
| 26 | x < 0+1 when CompareGT: ... > ... is false |
@@ -635,6 +679,20 @@ irGuardsCompare
| 109 | y < 0+0 when CompareLT: ... < ... is true |
| 109 | y >= 0 when CompareLT: ... < ... is false |
| 109 | y >= 0+0 when CompareLT: ... < ... is false |
| 126 | 1 != 0 when Constant: 1 is true |
| 126 | 1 == 0 when Constant: 1 is false |
| 126 | call to test3_condition != 0 when Call: call to test3_condition is true |
| 126 | call to test3_condition == 0 when Call: call to test3_condition is false |
| 131 | b != 0 when Load: b is true |
| 131 | b == 0 when Load: b is false |
| 137 | 0 != 0 when Constant: 0 is true |
| 137 | 0 == 0 when Constant: 0 is false |
| 146 | ! ... != 0 when LogicalNot: ! ... is true |
| 146 | ! ... == 0 when LogicalNot: ! ... is false |
| 152 | x != 0 when Load: x is true |
| 152 | x == 0 when Load: x is false |
| 152 | y != 0 when Load: y is true |
| 152 | y == 0 when Load: y is false |
| 156 | ... + ... != x+0 when CompareEQ: ... == ... is false |
| 156 | ... + ... == x+0 when CompareEQ: ... == ... is true |
| 156 | x != ... + ...+0 when CompareEQ: ... == ... is false |
@@ -673,6 +731,8 @@ irGuardsCompare
| 175 | call to foo != 0+0 when CompareEQ: ... == ... is false |
| 175 | call to foo == 0 when CompareEQ: ... == ... is true |
| 175 | call to foo == 0+0 when CompareEQ: ... == ... is true |
| 181 | x != 0 when Load: x is true |
| 181 | x == 0 when Load: x is false |
irGuardsControl
| test.c:7:9:7:13 | CompareGT: ... > ... | false | 11 | 11 |
| test.c:7:9:7:13 | CompareGT: ... > ... | true | 8 | 8 |
@@ -994,8 +1054,22 @@ irGuardsEnsure_const
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | 0 | 109 | 109 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | 0 | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:19:109:19 | Load: y | >= | 0 | 113 | 113 |
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 126 | 126 |
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 127 | 127 |
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 131 | 131 |
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 132 | 132 |
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 134 | 134 |
| test.c:126:12:126:26 | Call: call to test3_condition | test.c:126:12:126:26 | Call: call to test3_condition | != | 0 | 127 | 127 |
| test.c:131:7:131:7 | Load: b | test.c:131:7:131:7 | Load: b | != | 0 | 132 | 132 |
| test.c:137:7:137:7 | Constant: 0 | test.c:137:7:137:7 | Constant: 0 | == | 0 | 142 | 142 |
| test.c:146:7:146:8 | LogicalNot: ! ... | test.c:146:7:146:8 | LogicalNot: ! ... | != | 0 | 147 | 147 |
| test.c:152:10:152:10 | Load: x | test.c:152:10:152:10 | Load: x | != | 0 | 152 | 152 |
| test.c:152:15:152:15 | Load: y | test.c:152:15:152:15 | Load: y | != | 0 | 152 | 152 |
| test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | != | 0 | 175 | 175 |
| test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | == | 0 | 175 | 175 |
| test.c:181:9:181:9 | Load: x | test.c:181:9:181:9 | Load: x | != | 0 | 182 | 182 |
| test.c:181:9:181:9 | Load: x | test.c:181:9:181:9 | Load: x | == | 0 | 184 | 184 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:10 | Call: call to get | != | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | -1 | 34 | 34 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 32 | 32 |

View File

@@ -26,9 +26,19 @@
| test.c:137:7:137:7 | 0 |
| test.c:146:7:146:8 | ! ... |
| test.c:146:8:146:8 | x |
| test.c:152:8:152:8 | p |
| test.c:158:8:158:9 | ! ... |
| test.c:158:9:158:9 | p |
| test.c:164:8:164:8 | s |
| test.c:170:8:170:9 | ! ... |
| test.c:170:9:170:9 | s |
| test.cpp:18:8:18:10 | call to get |
| test.cpp:31:7:31:13 | ... == ... |
| test.cpp:42:13:42:20 | call to getABool |
| test.cpp:61:10:61:10 | i |
| test.cpp:74:10:74:10 | i |
| test.cpp:84:10:84:10 | i |
| test.cpp:93:6:93:6 | c |
| test.cpp:99:6:99:6 | f |
| test.cpp:105:6:105:14 | ... != ... |
| test.cpp:111:6:111:14 | ... != ... |

View File

@@ -22,6 +22,8 @@
| 17 | y >= 1+1 when ... > ... is true |
| 17 | y >= 2 when ... && ... is true |
| 17 | y >= 2 when ... > ... is true |
| 18 | call to get != 0 when call to get is true |
| 18 | call to get == 0 when call to get is false |
| 26 | 0 < x+0 when ... > ... is true |
| 26 | 0 >= x+0 when ... > ... is false |
| 26 | x < 0+1 when ... > ... is false |
@@ -107,6 +109,8 @@
| 85 | y != 0+0 when ... && ... is true |
| 85 | y == 0 when ... != ... is false |
| 85 | y == 0+0 when ... != ... is false |
| 93 | c != 0 when c is true |
| 93 | c == 0 when c is false |
| 94 | 0 != x+0 when ... != ... is true |
| 94 | 0 == x+0 when ... != ... is false |
| 94 | x != 0 when ... != ... is true |
@@ -119,6 +123,10 @@
| 102 | j < 10+0 when ... < ... is true |
| 102 | j >= 10 when ... < ... is false |
| 102 | j >= 10+0 when ... < ... is false |
| 105 | 0.0 != f+0 when ... != ... is true |
| 105 | 0.0 == f+0 when ... != ... is false |
| 105 | f != 0.0+0 when ... != ... is true |
| 105 | f == 0.0+0 when ... != ... is false |
| 109 | 0 != x+0 when ... == ... is false |
| 109 | 0 != x+0 when ... \|\| ... is false |
| 109 | 0 < y+1 when ... < ... is false |
@@ -137,3 +145,27 @@
| 109 | y >= 0 when ... \|\| ... is false |
| 109 | y >= 0+0 when ... < ... is false |
| 109 | y >= 0+0 when ... \|\| ... is false |
| 111 | 0.0 != i+0 when ... != ... is true |
| 111 | 0.0 == i+0 when ... != ... is false |
| 111 | i != 0.0+0 when ... != ... is true |
| 111 | i == 0.0+0 when ... != ... is false |
| 126 | 1 != 0 when 1 is true |
| 126 | 1 != 0 when ... && ... is true |
| 126 | 1 == 0 when 1 is false |
| 126 | call to test3_condition != 0 when ... && ... is true |
| 126 | call to test3_condition != 0 when call to test3_condition is true |
| 126 | call to test3_condition == 0 when call to test3_condition is false |
| 131 | b != 0 when b is true |
| 131 | b == 0 when b is false |
| 137 | 0 != 0 when 0 is true |
| 137 | 0 == 0 when 0 is false |
| 146 | ! ... != 0 when ! ... is true |
| 146 | ! ... == 0 when ! ... is false |
| 152 | p != 0 when p is true |
| 152 | p == 0 when p is false |
| 158 | ! ... != 0 when ! ... is true |
| 158 | ! ... == 0 when ! ... is false |
| 164 | s != 0 when s is true |
| 164 | s == 0 when s is false |
| 170 | ! ... != 0 when ! ... is true |
| 170 | ! ... == 0 when ! ... is false |

View File

@@ -79,6 +79,12 @@
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
| test.c:146:8:146:8 | x | false | 146 | 147 |
| test.c:152:8:152:8 | p | true | 152 | 154 |
| test.c:158:8:158:9 | ! ... | true | 158 | 160 |
| test.c:158:9:158:9 | p | false | 158 | 160 |
| test.c:164:8:164:8 | s | true | 164 | 166 |
| test.c:170:8:170:9 | ! ... | true | 170 | 172 |
| test.c:170:9:170:9 | s | false | 170 | 172 |
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
@@ -90,3 +96,7 @@
| test.cpp:61:10:61:10 | i | Case[1] | 65 | 66 |
| test.cpp:74:10:74:10 | i | Case[0..10] | 75 | 77 |
| test.cpp:74:10:74:10 | i | Case[11..20] | 78 | 79 |
| test.cpp:93:6:93:6 | c | true | 93 | 94 |
| test.cpp:99:6:99:6 | f | true | 99 | 100 |
| test.cpp:105:6:105:14 | ... != ... | true | 105 | 106 |
| test.cpp:111:6:111:14 | ... != ... | true | 111 | 112 |

View File

@@ -1,3 +1,4 @@
binary
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | < | test.c:7:13:7:13 | 0 | 1 | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | >= | test.c:7:13:7:13 | 0 | 1 | 7 | 9 |
| test.c:7:9:7:13 | ... > ... | test.c:7:13:7:13 | 0 | < | test.c:7:9:7:9 | x | 0 | 7 | 9 |
@@ -154,3 +155,109 @@
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 31 | 32 |
| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:6:105:6 | f | != | test.cpp:105:11:105:14 | 0.0 | 0 | 105 | 106 |
| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:11:105:14 | 0.0 | != | test.cpp:105:6:105:6 | f | 0 | 105 | 106 |
| test.cpp:111:6:111:14 | ... != ... | test.cpp:111:6:111:6 | i | != | test.cpp:111:11:111:14 | 0.0 | 0 | 111 | 112 |
| test.cpp:111:6:111:14 | ... != ... | test.cpp:111:11:111:14 | 0.0 | != | test.cpp:111:6:111:6 | i | 0 | 111 | 112 |
unary
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | < | 1 | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | >= | 1 | 7 | 9 |
| test.c:17:8:17:12 | ... < ... | test.c:17:8:17:8 | x | < | 0 | 17 | 17 |
| test.c:17:8:17:12 | ... < ... | test.c:17:8:17:8 | x | < | 0 | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | test.c:17:8:17:8 | x | < | 0 | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | test.c:17:17:17:17 | y | >= | 2 | 18 | 18 |
| test.c:17:17:17:21 | ... > ... | test.c:17:17:17:17 | y | >= | 2 | 18 | 18 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 2 | 2 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 31 | 34 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 34 | 34 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 39 | 42 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 42 | 42 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 42 | 44 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 45 | 45 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 45 | 47 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 51 | 53 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 56 | 58 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 58 | 58 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 58 | 66 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 62 | 62 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | >= | 1 | 26 | 28 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | < | 10 | 34 | 34 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 2 | 2 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 39 | 42 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 42 | 42 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 42 | 44 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 45 | 45 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 45 | 47 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 51 | 53 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 56 | 58 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 58 | 58 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 58 | 66 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 62 | 62 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 42 | 42 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 42 | 44 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 45 | 45 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 45 | 47 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | 1 | 42 | 42 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | 1 | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | 1 | 45 | 45 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | 1 | 45 | 47 |
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | >= | 1 | 45 | 47 |
| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | 0 | 58 | 58 |
| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | 0 | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | test.c:58:9:58:9 | x | != | 0 | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | test.c:58:19:58:19 | y | >= | 0 | 62 | 62 |
| test.c:58:19:58:23 | ... < ... | test.c:58:19:58:19 | y | >= | 0 | 62 | 62 |
| test.c:75:9:75:14 | ... == ... | test.c:75:9:75:9 | x | != | 0 | 78 | 79 |
| test.c:75:9:75:14 | ... == ... | test.c:75:9:75:9 | x | == | 0 | 75 | 77 |
| test.c:85:8:85:13 | ... == ... | test.c:85:8:85:8 | x | == | 0 | 85 | 85 |
| test.c:85:8:85:13 | ... == ... | test.c:85:8:85:8 | x | == | 0 | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | test.c:85:8:85:8 | x | == | 0 | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | test.c:85:18:85:18 | y | != | 0 | 86 | 86 |
| test.c:85:18:85:23 | ... != ... | test.c:85:18:85:18 | y | != | 0 | 86 | 86 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | != | 0 | 94 | 96 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 70 | 70 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 99 | 102 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 102 | 102 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 107 | 109 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 109 | 109 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 109 | 117 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 113 | 113 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | < | 10 | 102 | 102 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 70 | 70 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 107 | 109 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 109 | 109 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 109 | 117 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 113 | 113 |
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 126 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
| test.c:131:7:131:7 | b | test.c:131:7:131:7 | b | != | 0 | 131 | 132 |
| test.c:137:7:137:7 | 0 | test.c:137:7:137:7 | 0 | == | 0 | 142 | 136 |
| test.c:146:7:146:8 | ! ... | test.c:146:7:146:8 | ! ... | != | 0 | 146 | 147 |
| test.c:152:8:152:8 | p | test.c:152:8:152:8 | p | != | 0 | 152 | 154 |
| test.c:158:8:158:9 | ! ... | test.c:158:8:158:9 | ! ... | != | 0 | 158 | 160 |
| test.c:164:8:164:8 | s | test.c:164:8:164:8 | s | != | 0 | 164 | 166 |
| test.c:170:8:170:9 | ! ... | test.c:170:8:170:9 | ! ... | != | 0 | 170 | 172 |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 |
| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 0 | 62 | 64 |
| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 1 | 65 | 66 |
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | < | 11 | 75 | 77 |
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | < | 21 | 78 | 79 |
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 0 | 75 | 77 |
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 11 | 78 | 79 |
| test.cpp:93:6:93:6 | c | test.cpp:93:6:93:6 | c | != | 0 | 93 | 94 |

View File

@@ -7,8 +7,9 @@
import cpp
import semmle.code.cpp.controlflow.Guards
from GuardCondition guard, Expr left, Expr right, int k, int start, int end, string op
where
query predicate binary(
GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end
) {
exists(BasicBlock block |
guard.ensuresLt(left, right, k, block, true) and op = "<"
or
@@ -20,4 +21,18 @@ where
|
block.hasLocationInfo(_, start, _, end, _)
)
select guard, left, op, right, k, start, end
}
query predicate unary(GuardCondition guard, Expr left, string op, int k, int start, int end) {
exists(BasicBlock block |
guard.ensuresLt(left, k, block, true) and op = "<"
or
guard.ensuresLt(left, k, block, false) and op = ">="
or
guard.ensuresEq(left, k, block, true) and op = "=="
or
guard.ensuresEq(left, k, block, false) and op = "!="
|
block.hasLocationInfo(_, start, _, end, _)
)
}

View File

@@ -147,3 +147,27 @@ void test5(int x) {
test3();
}
}
void test6(char* p) {
if(p) {
}
}
void test7(char* p) {
if(!p) {
}
}
void test8(short s) {
if(s) {
}
}
void test9(short s) {
if(!s) {
}
}

View File

@@ -85,4 +85,30 @@ void test_switches_default(int i) {
default:
use1(i);
}
}
}
void use(...);
void pointer_comparison(char* c) {
if(c) {
use(c);
}
}
void implicit_float_comparison(float f) {
if(f) {
use(f);
}
}
void explicit_float_comparison(float f) {
if(f != 0.0f) {
use(f);
}
}
void int_float_comparison(int i) {
if(i != 0.0f) {
use(i);
}
}

View File

@@ -228,7 +228,6 @@ irFlow
| test.cpp:333:17:333:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:343:10:343:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:343:10:343:18 | globalVar |
@@ -260,7 +259,6 @@ irFlow
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:566:10:566:19 | * ... |
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:568:10:568:19 | * ... |
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:572:10:572:19 | * ... |
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:578:10:578:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:566:10:566:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:568:10:568:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:572:10:572:19 | * ... |

View File

@@ -346,7 +346,7 @@ namespace FlowThroughGlobals {
void taintAndCall() {
globalVar = source();
calledAfterTaint();
sink(globalVar); // $ ast ir=333:17 ir=347:17
sink(globalVar); // $ ast ir
}
}
@@ -575,7 +575,7 @@ namespace IndirectFlowThroughGlobals {
void taintAndCall() {
globalInt = indirect_source();
calledAfterTaint();
sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17
sink(*globalInt); // $ ir MISSING: ast=562:17 ast=576:17
}
}

View File

@@ -66,8 +66,8 @@ public:
insert_iterator_by_trait operator++(int);
insert_iterator_by_trait &operator--();
insert_iterator_by_trait operator--(int);
insert_iterator_by_trait operator*();
insert_iterator_by_trait operator=(int x);
insert_iterator_by_trait& operator*();
insert_iterator_by_trait& operator=(int x);
};
template<>

View File

@@ -389,7 +389,7 @@ void test_vector_output_iterator(int b) {
*i9 = source();
taint_vector_output_iterator(i9);
sink(v9); // $ ast=330:10 MISSING: ir SPURIOUS: ast=389:8
sink(v9); // $ ast=330:10 ir SPURIOUS: ast=389:8
std::vector<int>::iterator i10 = v10.begin();
vector_iterator_assign_wrapper(i10, 10);
@@ -440,14 +440,14 @@ void test_vector_inserter(char *source_string) {
std::vector<std::string> out;
auto it = std::back_inserter(out);
*++it = std::string(source_string);
sink(out); // $ ast MISSING: ir
sink(out); // $ ast,ir
}
{
std::vector<int> out;
auto it = std::back_inserter(out);
*++it = source();
sink(out); // $ ast MISSING: ir
sink(out); // $ ast,ir
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -2191,6 +2191,7 @@ public:
void set_x(char y) { *x = y; }
char get_x() { return *x; }
operator bool() const;
};
constexpr bool initialization_with_destructor_bool = true;
@@ -2432,7 +2433,7 @@ void initialization_with_temp_destructor() {
}
void param_with_destructor_by_value(ClassWithDestructor c) {
// The call to ~ClassWithDestructor::ClassWithDestructor() seems to be missing here.
// The call to ~ClassWithDestructor::ClassWithDestructor() happens on the side of the caller
}
void param_with_destructor_by_pointer(ClassWithDestructor* c) {
@@ -2481,4 +2482,74 @@ namespace rvalue_conversion_with_destructor {
}
}
void destructor_without_block(bool b)
{
if (b)
ClassWithDestructor c;
if (b)
ClassWithDestructor d;
else
ClassWithDestructor e;
while (b)
ClassWithDestructor f;
for(int i = 0; i < 42; ++i)
ClassWithDestructor g;
}
void destruction_in_switch_1(int c) {
switch (c) {
case 0: {
ClassWithDestructor x;
break;
}
}
}
void destruction_in_switch_2(int c) {
switch (ClassWithDestructor y; c) {
case 0: {
break;
}
default: {
break;
}
}
}
void destruction_in_switch_3(int c) {
switch (ClassWithDestructor y; c) {
case 0: {
ClassWithDestructor x;
break;
}
default: {
break;
}
}
}
void destructor_possibly_not_handled() {
ClassWithDestructor x;
try {
throw 42;
}
catch(char) {
}
}
ClassWithDestructor getClassWithDestructor();
void this_inconsistency(bool b) {
if (const ClassWithDestructor& a = getClassWithDestructor())
;
}
void constexpr_inconsistency(bool b) {
if constexpr (const ClassWithDestructor& a = getClassWithDestructor(); initialization_with_destructor_bool)
;
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -21,6 +21,7 @@ lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
| ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() |
| ir.cpp:2551:48:2551:71 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2550:6:2550:28 | void constexpr_inconsistency(bool) | void constexpr_inconsistency(bool) |
| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() |
| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() |
| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) |
@@ -36,6 +37,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -4,12 +4,6 @@ uniqueType
uniqueNodeLocation
missingLocation
uniqueNodeToString
| builtin.c:5:5:5:11 | (no string representation) | Node should have one toString but has 0. |
| misc.c:227:7:227:28 | (no string representation) | Node should have one toString but has 0. |
| static_init_templates.cpp:80:18:80:23 | (no string representation) | Node should have one toString but has 0. |
| static_init_templates.cpp:80:18:80:23 | (no string representation) | Node should have one toString but has 0. |
| static_init_templates.cpp:89:18:89:23 | (no string representation) | Node should have one toString but has 0. |
| static_init_templates.cpp:89:18:89:23 | (no string representation) | Node should have one toString but has 0. |
parameterCallable
localFlowIsLocal
readStepIsLocal

View File

@@ -1,41 +0,0 @@
WARNING: Type GVN has been deprecated and may be removed in future (ast_gvn.ql:4,6-9)
| test.cpp:5:3:5:3 | x | 5:c3-c3 6:c3-c3 |
| test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 |
| test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 7:c7-c7 |
| test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 |
| test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 |
| test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 |
| test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 |
| test.cpp:16:7:16:24 | ... + ... | 16:c7-c24 17:c7-c24 18:c7-c7 |
| test.cpp:16:12:16:13 | p1 | 16:c12-c13 17:c12-c13 |
| test.cpp:16:17:16:24 | global01 | 16:c17-c24 17:c17-c24 |
| test.cpp:29:7:29:8 | p0 | 29:c7-c8 31:c7-c8 |
| test.cpp:29:7:29:13 | ... + ... | 29:c7-c13 31:c7-c13 |
| test.cpp:29:12:29:13 | p1 | 29:c12-c13 31:c12-c13 |
| test.cpp:31:7:31:24 | ... + ... | 31:c7-c24 32:c7-c7 |
| test.cpp:43:7:43:8 | p0 | 43:c7-c8 45:c7-c8 |
| test.cpp:43:7:43:13 | ... + ... | 43:c7-c13 45:c7-c13 |
| test.cpp:43:12:43:13 | p1 | 43:c12-c13 45:c12-c13 |
| test.cpp:44:9:44:9 | 0 | 44:c9-c9 51:c25-c25 53:c18-c21 56:c39-c42 59:c17-c20 88:c12-c12 |
| test.cpp:45:7:45:24 | ... + ... | 45:c7-c24 46:c7-c7 |
| test.cpp:53:10:53:13 | (int)... | 53:c10-c13 56:c21-c24 |
| test.cpp:53:10:53:13 | * ... | 53:c10-c13 56:c21-c24 |
| test.cpp:53:11:53:13 | str | 53:c11-c13 56:c22-c24 |
| test.cpp:53:18:53:21 | 0 | 53:c18-c21 56:c39-c42 59:c17-c20 |
| test.cpp:56:13:56:16 | (int)... | 56:c13-c16 56:c31-c34 59:c9-c12 |
| test.cpp:56:13:56:16 | * ... | 56:c13-c16 56:c31-c34 59:c9-c12 |
| test.cpp:56:14:56:16 | ptr | 56:c14-c16 56:c32-c34 56:c47-c49 59:c10-c12 |
| test.cpp:62:5:62:10 | result | 62:c5-c10 65:c10-c15 |
| test.cpp:77:20:77:30 | (signed short)... | 77:c20-c30 79:c7-c7 |
| test.cpp:79:11:79:14 | vals | 79:c11-c14 79:c24-c27 |
| test.cpp:105:11:105:12 | (Base *)... | 105:c11-c12 106:c14-c35 107:c11-c12 |
| test.cpp:105:11:105:12 | pd | 105:c11-c12 106:c33-c34 |
| test.cpp:105:15:105:15 | b | 105:c15-c15 107:c15-c15 109:c10-c10 |
| test.cpp:125:11:125:12 | pa | 125:c11-c12 126:c11-c12 128:c3-c4 129:c11-c12 |
| test.cpp:125:15:125:15 | x | 125:c15-c15 126:c15-c15 128:c7-c7 |
| test.cpp:136:11:136:18 | global_a | 136:c11-c18 137:c11-c18 139:c3-c10 |
| test.cpp:136:21:136:21 | x | 136:c21-c21 137:c21-c21 139:c13-c13 |
| test.cpp:144:11:144:12 | pa | 144:c11-c12 145:c11-c12 147:c3-c4 149:c11-c12 |
| test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 |
| test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 |
| test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 |

View File

@@ -1,11 +0,0 @@
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumberingImpl
from GVN g
where strictcount(g.getAnExpr()) > 1
select g,
strictconcat(Location loc |
loc = g.getAnExpr().getLocation()
|
loc.getStartLine() + ":c" + loc.getStartColumn() + "-c" + loc.getEndColumn(), " "
)

View File

@@ -1,3 +0,0 @@
WARNING: Predicate globalValueNumber has been deprecated and may be removed in future (ast_uniqueness.ql:7,13-30)
WARNING: Predicate globalValueNumber has been deprecated and may be removed in future (ast_uniqueness.ql:8,30-47)
WARNING: Type GVN has been deprecated and may be removed in future (ast_uniqueness.ql:8,18-21)

View File

@@ -1,8 +0,0 @@
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumberingImpl
// Every expression should have exactly one GVN.
// So this query should have zero results.
from Expr e
where count(globalValueNumber(e)) != 1
select e, concat(GVN g | g = globalValueNumber(e) | g.getKind(), ", ")

View File

@@ -1,130 +0,0 @@
WARNING: Predicate globalValueNumber has been deprecated and may be removed in future (diff_ir_expr.ql:8,29-51)
| test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only |
| test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only |
| test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only |
| test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only |
| test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only |
| test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only |
| test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only |
| test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only |
| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only |
| test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only |
| test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only |
| test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only |
| test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only |
| test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only |
| test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only |
| test.cpp:43:7:43:24 | ... + ... | test.cpp:46:7:46:7 | x | IR only |
| test.cpp:43:17:43:24 | global03 | test.cpp:45:17:45:24 | global03 | IR only |
| test.cpp:44:3:44:5 | * ... | test.cpp:44:4:44:5 | p2 | IR only |
| test.cpp:44:3:44:9 | ... = ... | test.cpp:44:3:44:9 | ... = ... | AST only |
| test.cpp:44:4:44:5 | p2 | test.cpp:44:3:44:5 | * ... | IR only |
| test.cpp:44:9:44:9 | 0 | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:45:3:45:3 | x | test.cpp:43:3:43:3 | x | IR only |
| test.cpp:45:3:45:24 | ... = ... | test.cpp:45:3:45:24 | ... = ... | AST only |
| test.cpp:45:7:45:24 | ... + ... | test.cpp:43:7:43:24 | ... + ... | IR only |
| test.cpp:45:17:45:24 | global03 | test.cpp:43:17:43:24 | global03 | IR only |
| test.cpp:46:3:46:7 | ... = ... | test.cpp:46:3:46:7 | ... = ... | AST only |
| test.cpp:46:7:46:7 | x | test.cpp:43:7:43:24 | ... + ... | IR only |
| test.cpp:51:25:51:25 | 0 | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:51:25:51:25 | (unsigned int)... | test.cpp:51:25:51:25 | (unsigned int)... | AST only |
| test.cpp:53:10:53:13 | (int)... | test.cpp:53:10:53:13 | (int)... | AST only |
| test.cpp:53:10:53:13 | (int)... | test.cpp:56:21:56:24 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:55:5:55:15 | ... = ... | test.cpp:55:5:55:15 | ... = ... | AST only |
| test.cpp:56:12:56:25 | (...) | test.cpp:56:12:56:25 | (...) | AST only |
| test.cpp:56:12:56:43 | ... && ... | test.cpp:56:12:56:43 | ... && ... | AST only |
| test.cpp:56:13:56:16 | (int)... | test.cpp:56:13:56:16 | (int)... | AST only |
| test.cpp:56:13:56:16 | (int)... | test.cpp:56:31:56:34 | (int)... | AST only |
| test.cpp:56:13:56:16 | (int)... | test.cpp:59:9:59:12 | (int)... | AST only |
| test.cpp:56:21:56:24 | (int)... | test.cpp:53:10:53:13 | (int)... | AST only |
| test.cpp:56:21:56:24 | (int)... | test.cpp:56:21:56:24 | (int)... | AST only |
| test.cpp:56:30:56:43 | (...) | test.cpp:56:30:56:43 | (...) | AST only |
| test.cpp:56:31:56:34 | (int)... | test.cpp:56:13:56:16 | (int)... | AST only |
| test.cpp:56:31:56:34 | (int)... | test.cpp:56:31:56:34 | (int)... | AST only |
| test.cpp:56:31:56:34 | (int)... | test.cpp:59:9:59:12 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:56:47:56:51 | ... ++ | test.cpp:56:47:56:51 | ... ++ | AST only |
| test.cpp:59:9:59:12 | (int)... | test.cpp:56:13:56:16 | (int)... | AST only |
| test.cpp:59:9:59:12 | (int)... | test.cpp:56:31:56:34 | (int)... | AST only |
| test.cpp:59:9:59:12 | (int)... | test.cpp:59:9:59:12 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:62:5:62:12 | ... ++ | test.cpp:62:5:62:12 | ... ++ | AST only |
| test.cpp:77:20:77:28 | call to getAValue | test.cpp:79:7:79:7 | v | IR only |
| test.cpp:77:20:77:30 | (signed short)... | test.cpp:77:20:77:30 | (signed short)... | AST only |
| test.cpp:77:20:77:30 | (signed short)... | test.cpp:79:7:79:7 | v | AST only |
| test.cpp:79:7:79:7 | (int)... | test.cpp:79:7:79:7 | (int)... | AST only |
| test.cpp:79:7:79:7 | v | test.cpp:77:20:77:28 | call to getAValue | IR only |
| test.cpp:79:7:79:7 | v | test.cpp:77:20:77:30 | (signed short)... | AST only |
| test.cpp:79:11:79:20 | (int)... | test.cpp:79:11:79:20 | (int)... | AST only |
| test.cpp:79:24:79:33 | (int)... | test.cpp:79:24:79:33 | (int)... | AST only |
| test.cpp:80:5:80:19 | ... = ... | test.cpp:80:5:80:19 | ... = ... | AST only |
| test.cpp:80:9:80:19 | (signed short)... | test.cpp:80:9:80:19 | (signed short)... | AST only |
| test.cpp:88:3:88:20 | ... = ... | test.cpp:88:3:88:20 | ... = ... | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:88:12:88:12 | (void *)... | test.cpp:88:12:88:12 | (void *)... | AST only |
| test.cpp:92:11:92:16 | ... = ... | test.cpp:92:15:92:16 | 10 | IR only |
| test.cpp:92:11:92:16 | ... = ... | test.cpp:93:10:93:10 | x | IR only |
| test.cpp:92:15:92:16 | 10 | test.cpp:92:11:92:16 | ... = ... | IR only |
| test.cpp:92:15:92:16 | 10 | test.cpp:93:10:93:10 | x | IR only |
| test.cpp:93:10:93:10 | x | test.cpp:92:11:92:16 | ... = ... | IR only |
| test.cpp:93:10:93:10 | x | test.cpp:92:15:92:16 | 10 | IR only |
| test.cpp:105:11:105:12 | (Base *)... | test.cpp:105:11:105:12 | (Base *)... | AST only |
| test.cpp:105:11:105:12 | (Base *)... | test.cpp:106:14:106:35 | static_cast<Base *>... | AST only |
| test.cpp:105:11:105:12 | (Base *)... | test.cpp:107:11:107:12 | pb | AST only |
| test.cpp:105:11:105:12 | pd | test.cpp:107:11:107:12 | pb | IR only |
| test.cpp:106:14:106:35 | static_cast<Base *>... | test.cpp:105:11:105:12 | (Base *)... | AST only |
| test.cpp:106:14:106:35 | static_cast<Base *>... | test.cpp:106:14:106:35 | static_cast<Base *>... | AST only |
| test.cpp:106:14:106:35 | static_cast<Base *>... | test.cpp:107:11:107:12 | pb | AST only |
| test.cpp:106:33:106:34 | pd | test.cpp:107:11:107:12 | pb | IR only |
| test.cpp:107:11:107:12 | pb | test.cpp:105:11:105:12 | (Base *)... | AST only |
| test.cpp:107:11:107:12 | pb | test.cpp:105:11:105:12 | pd | IR only |
| test.cpp:107:11:107:12 | pb | test.cpp:106:14:106:35 | static_cast<Base *>... | AST only |
| test.cpp:107:11:107:12 | pb | test.cpp:106:33:106:34 | pd | IR only |
| test.cpp:113:3:113:5 | a | test.cpp:115:3:115:5 | a | IR only |
| test.cpp:115:3:115:5 | a | test.cpp:113:3:113:5 | a | IR only |
| test.cpp:125:15:125:15 | x | test.cpp:128:7:128:7 | x | AST only |
| test.cpp:126:15:126:15 | x | test.cpp:128:7:128:7 | x | AST only |
| test.cpp:128:3:128:11 | ... = ... | test.cpp:128:3:128:11 | ... = ... | AST only |
| test.cpp:128:7:128:7 | x | test.cpp:125:15:125:15 | x | AST only |
| test.cpp:128:7:128:7 | x | test.cpp:126:15:126:15 | x | AST only |
| test.cpp:128:11:128:11 | n | test.cpp:129:15:129:15 | x | IR only |
| test.cpp:129:15:129:15 | x | test.cpp:128:11:128:11 | n | IR only |
| test.cpp:136:21:136:21 | x | test.cpp:139:13:139:13 | x | AST only |
| test.cpp:137:21:137:21 | x | test.cpp:139:13:139:13 | x | AST only |
| test.cpp:139:3:139:24 | ... = ... | test.cpp:139:3:139:24 | ... = ... | AST only |
| test.cpp:139:13:139:13 | x | test.cpp:136:21:136:21 | x | AST only |
| test.cpp:139:13:139:13 | x | test.cpp:137:21:137:21 | x | AST only |
| test.cpp:144:15:144:15 | x | test.cpp:149:15:149:15 | x | IR only |
| test.cpp:145:15:145:15 | y | test.cpp:147:7:147:7 | y | AST only |
| test.cpp:147:3:147:18 | ... = ... | test.cpp:147:3:147:18 | ... = ... | AST only |
| test.cpp:147:7:147:7 | y | test.cpp:145:15:145:15 | y | AST only |
| test.cpp:149:15:149:15 | x | test.cpp:144:15:144:15 | x | IR only |
| test.cpp:156:3:156:17 | ... = ... | test.cpp:156:3:156:17 | ... = ... | AST only |

View File

@@ -1,15 +0,0 @@
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumberingImpl as AST
import semmle.code.cpp.ir.internal.ASTValueNumbering as IR
import semmle.code.cpp.ir.IR
Expr ir(Expr e) { result = IR::globalValueNumber(e).getAnExpr() }
Expr ast(Expr e) { result = AST::globalValueNumber(e).getAnExpr() }
from Expr e, Expr evn, string note
where
evn = ast(e) and not evn = ir(e) and note = "AST only"
or
evn = ir(e) and not evn = ast(e) and note = "IR only"
select e, evn, note

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