Compare commits

...

238 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
Paolo Tranquilli
2590d8a27f Merge branch 'main' into redsun82/go 2024-04-30 11:00:27 +02:00
Ian Lynagh
676bcf39a5 Java: Remove support for deprecated ODASA_BUILD_ERROR_DIR env var 2024-04-29 18:02:28 +01: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
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
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
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
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
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
Paolo Tranquilli
0f387eeac2 Go: add vendor update to //go:gen 2024-04-26 16:31:04 +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
Paolo Tranquilli
146d84bbf8 Go: rework makefile 2024-04-26 15:20:33 +02:00
Michael Nebel
f95b33049e Java: Improve the Api sources and sinks implementation. 2024-04-26 14:12:41 +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
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
Mario Campos
d7c784ef2f Initial commit of experimental query cpp/guarded-free. 2024-04-25 16:29:37 -05: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
Anders Schack-Mulligen
830b83f653 Dataflow: Use doublyBoundedFastTC. 2024-04-23 13:07:20 +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
Chad Bentz
78ddb998a2 Merge branch 'main' into patch-1 2024-04-12 09:09:43 -04: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
312 changed files with 13073 additions and 11135 deletions

View File

@@ -14,6 +14,10 @@ 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

View File

@@ -24,5 +24,5 @@ jobs:
extra_args: >
buildifier --all-files 2>&1 ||
(
echo -e "In order to format all bazel files, please run:\n bazel run //:buildifier"; exit 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

@@ -26,7 +26,14 @@ repos:
name: Format bazel files
files: \.(bazel|bzl)
language: system
entry: bazel run //:buildifier
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

View File

@@ -1,9 +0,0 @@
load("@buildifier_prebuilt//:rules.bzl", "buildifier")
buildifier(
name = "buildifier",
exclude_patterns = [
"./.git/*",
],
lint_mode = "fix",
)

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,7 @@ 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)
@@ -52,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

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

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(

View File

@@ -1665,3 +1665,311 @@ class DataFlowSecondLevelScope extends TDataFlowSecondLevelScope {
/** 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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.9.11
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

@@ -148,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 |
@@ -186,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 |
@@ -487,8 +507,27 @@ 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 |
@@ -640,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 |
@@ -678,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 |
@@ -999,8 +1054,21 @@ 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 |

View File

@@ -26,6 +26,12 @@
| 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 |

View File

@@ -149,3 +149,23 @@
| 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 |

View File

@@ -234,6 +234,21 @@ unary
| 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 |

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

@@ -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;
@@ -2498,4 +2499,57 @@ void destructor_without_block(bool b)
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

@@ -26,6 +26,8 @@
| test.cpp:128:15:128:16 | v4 |
| test.cpp:185:10:185:12 | cpy |
| test.cpp:199:10:199:12 | cpy |
| test.cpp:208:7:208:7 | a |
| test.cpp:214:7:214:7 | a |
| test_free.cpp:11:10:11:10 | a |
| test_free.cpp:14:10:14:10 | a |
| test_free.cpp:16:10:16:10 | a |

View File

@@ -1,4 +1,6 @@
edges
| test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | provenance | |
| test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215:2 | a | provenance | |
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | provenance | |
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | provenance | |
| test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | provenance | |
@@ -31,6 +33,10 @@ edges
| test_free.cpp:322:12:322:12 | pointer to operator delete output argument | test_free.cpp:324:5:324:6 | * ... | provenance | |
| test_free.cpp:331:12:331:12 | pointer to operator delete output argument | test_free.cpp:332:5:332:6 | * ... | provenance | |
nodes
| test.cpp:208:7:208:7 | pointer to free output argument | semmle.label | pointer to free output argument |
| test.cpp:209:2:209:2 | a | semmle.label | a |
| test.cpp:214:7:214:7 | pointer to free output argument | semmle.label | pointer to free output argument |
| test.cpp:215:2:215:2 | a | semmle.label | a |
| test_free.cpp:11:10:11:10 | pointer to free output argument | semmle.label | pointer to free output argument |
| test_free.cpp:12:5:12:5 | a | semmle.label | a |
| test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... |
@@ -82,6 +88,8 @@ nodes
| test_free.cpp:332:5:332:6 | * ... | semmle.label | * ... |
subpaths
#select
| test.cpp:209:2:209:2 | a | test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | Memory may have been previously freed by $@. | test.cpp:208:2:208:5 | call to free | call to free |
| test.cpp:215:2:215:2 | a | test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215:2 | a | Memory may have been previously freed by $@. | test.cpp:214:2:214:5 | call to free | call to free |
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:13:5:13:6 | * ... | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |

View File

@@ -114,7 +114,7 @@ int main()
mc2->method2();
delete mc2;
}
{
void *v1 = malloc(100);
int *i2 = (int *)malloc(100);
@@ -198,3 +198,19 @@ void test_strndupa_dealloc() {
char *cpy = strndupa(msg, 4);
free(cpy); // BAD [NOT DETECTED]
}
// ---
void test_reassignment() {
char *a = (char *)malloc(128);
char *b = (char *)malloc(128);
free(a);
a[0] = 0; // BAD
a = b;
a[0] = 0; // GOOD
free(a);
a[0] = 0; // BAD
}

View File

@@ -3,7 +3,7 @@
void C6317_positive(int i)
{
if (i & !FLAGS) // BUG
if (i & !FLAGS) // BUG
{
}
}
@@ -71,3 +71,22 @@ void macroUsage(unsigned int arg1, unsigned int arg2)
}
}
void bool_examples(bool a, bool b)
{
if (a & !b) // dubious (confusing intent, but shouldn't produce a wrong result)
{
}
if (a & ~b)
{
}
if (a && ~b)
{
}
if (a && !b)
{
}
}

View File

@@ -14,3 +14,4 @@
| IncorrectNotOperatorUsage.cpp:48:9:48:18 | ... \| ... | Usage of a logical not (!) expression as a bitwise operator. |
| IncorrectNotOperatorUsage.cpp:49:9:49:20 | ... \| ... | Usage of a logical not (!) expression as a bitwise operator. |
| IncorrectNotOperatorUsage.cpp:70:10:70:34 | ... \| ... | Usage of a logical not (!) expression as a bitwise operator. |
| IncorrectNotOperatorUsage.cpp:77:9:77:14 | ... & ... | Usage of a logical not (!) expression as a bitwise operator. |

View File

@@ -0,0 +1,5 @@
| test.cpp:680:30:680:30 | call to operator[] | This object is destroyed at the end of the full-expression. |
| test.cpp:683:31:683:32 | call to at | This object is destroyed at the end of the full-expression. |
| test.cpp:702:27:702:27 | call to operator[] | This object is destroyed at the end of the full-expression. |
| test.cpp:727:23:727:23 | call to operator[] | This object is destroyed at the end of the full-expression. |
| test.cpp:735:23:735:23 | call to operator[] | This object is destroyed at the end of the full-expression. |

View File

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

View File

@@ -686,7 +686,7 @@ void test() {
for (auto x : returnRef()[0]) {} // GOOD
for (auto x : returnRef().at(0)) {} // GOOD
for(auto it = returnValue().begin(); it != returnValue().end(); ++it) {} // BAD
for(auto it = returnValue().begin(); it != returnValue().end(); ++it) {} // BAD [NOT DETECTED]
{
auto v = returnValue();
@@ -792,4 +792,13 @@ void test4() {
// function we may end up in the destructor call `chunk.~A()`in `A.foo`. This destructor
// call can flow to `begin` through the back-edge and cause a strange FP.
auto zero = A().size();
}
void test5(int i)
{
while(i < 10) {
const auto& vvs = returnValue();
for(const auto& vs : vvs) { }
++i;
} // GOOD
}

View File

@@ -1,13 +1,13 @@
| test.cpp:165:34:165:38 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:166:39:166:43 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:167:44:167:48 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:169:29:169:33 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:178:37:178:41 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:181:39:181:43 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:183:37:183:41 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:187:34:187:37 | call to data | The underlying string object is destroyed after the call to 'data' returns. |
| test.cpp:188:39:188:42 | call to data | The underlying string object is destroyed after the call to 'data' returns. |
| test.cpp:189:44:189:47 | call to data | The underlying string object is destroyed after the call to 'data' returns. |
| test.cpp:191:29:191:32 | call to data | The underlying string object is destroyed after the call to 'data' returns. |
| test.cpp:193:47:193:51 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:195:31:195:35 | call to c_str | The underlying string object is destroyed after the call to 'c_str' returns. |
| test.cpp:165:34:165:38 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:166:39:166:43 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:167:44:167:48 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:169:29:169:33 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:178:37:178:41 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:181:39:181:43 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:183:37:183:41 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:187:34:187:37 | call to data | The underlying temporary string object is destroyed after the call to 'data' returns. |
| test.cpp:188:39:188:42 | call to data | The underlying temporary string object is destroyed after the call to 'data' returns. |
| test.cpp:189:44:189:47 | call to data | The underlying temporary string object is destroyed after the call to 'data' returns. |
| test.cpp:191:29:191:32 | call to data | The underlying temporary string object is destroyed after the call to 'data' returns. |
| test.cpp:193:47:193:51 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |
| test.cpp:195:31:195:35 | call to c_str | The underlying temporary string object is destroyed after the call to 'c_str' returns. |

View File

@@ -22,3 +22,4 @@
| test.cpp:416:2:418:2 | for(...;...;...) ... | test.cpp:416:18:416:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:424:2:425:2 | for(...;...;...) ... | test.cpp:424:18:424:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:433:2:434:2 | for(...;...;...) ... | test.cpp:433:18:433:22 | 0 | 0 | | { ... } | 0 | return ... |
| test.cpp:559:3:564:3 | while (...) ... | test.cpp:559:9:559:15 | call to getBool | | call to getBool | { ... } | call to getBool | ExprStmt |

View File

@@ -13,6 +13,7 @@ nodes
| test.cpp:458:6:458:6 | definition of x | semmle.label | definition of x |
| test.cpp:464:6:464:6 | definition of x | semmle.label | definition of x |
| test.cpp:471:6:471:6 | definition of x | semmle.label | definition of x |
| test.cpp:557:15:557:15 | definition of r | semmle.label | definition of r |
#select
| test.cpp:12:6:12:8 | foo | test.cpp:11:6:11:8 | definition of foo | test.cpp:11:6:11:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo |
| test.cpp:113:6:113:8 | foo | test.cpp:111:6:111:8 | definition of foo | test.cpp:111:6:111:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo |
@@ -27,3 +28,4 @@ nodes
| test.cpp:460:7:460:7 | x | test.cpp:458:6:458:6 | definition of x | test.cpp:458:6:458:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:458:6:458:6 | x | x |
| test.cpp:467:2:467:2 | x | test.cpp:464:6:464:6 | definition of x | test.cpp:464:6:464:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:464:6:464:6 | x | x |
| test.cpp:474:7:474:7 | x | test.cpp:471:6:471:6 | definition of x | test.cpp:471:6:471:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:471:6:471:6 | x | x |
| test.cpp:567:7:567:7 | r | test.cpp:557:15:557:15 | definition of r | test.cpp:557:15:557:15 | definition of r | The variable $@ may not be initialized at this access. | test.cpp:557:15:557:15 | r | r |

View File

@@ -1,6 +1,6 @@
// Semmle test cases for rule CWE-457.
void use(int data);
void use(...);
void test1() {
int foo = 1;
@@ -544,4 +544,25 @@ class StaticMethodClass{
int static_method_false_positive(){
StaticMethodClass *t;
int i = t->get(); // GOOD: the `get` method is static and this is equivalent to StaticMethodClass::get()
}
struct LinkedList
{
LinkedList* next;
};
bool getBool();
void test45() {
LinkedList *r, *s, **rP = &r;
while(getBool())
{
s = new LinkedList;
*rP = s;
rP = &s->next;
}
*rP = NULL;
use(r); // GOOD [FALSE POSITIVE]
}

View File

@@ -41,99 +41,99 @@
| BoxedInt::~BoxedInt | true | 481 | 483 | |
| BoxedInt::~BoxedInt | true | 483 | 222 | |
| BoxedInt::~BoxedInt | true | 485 | 474 | |
| NonTrivial::NonTrivial | false | 543 | 543 | NonTrivial |
| NonTrivial::operator= | false | 549 | 549 | operator= |
| NonTrivial::~NonTrivial | false | 557 | 557 | ~NonTrivial |
| NonTrivial::~NonTrivial | false | 563 | 563 | return ... |
| NonTrivial::~NonTrivial | false | 565 | 565 | { ... } |
| NonTrivial::~NonTrivial | true | 563 | 557 | |
| NonTrivial::~NonTrivial | true | 565 | 563 | |
| NonTrivial::NonTrivial | false | 544 | 544 | NonTrivial |
| NonTrivial::operator= | false | 550 | 550 | operator= |
| NonTrivial::~NonTrivial | false | 558 | 558 | ~NonTrivial |
| NonTrivial::~NonTrivial | false | 564 | 564 | return ... |
| NonTrivial::~NonTrivial | false | 566 | 566 | { ... } |
| NonTrivial::~NonTrivial | true | 564 | 558 | |
| NonTrivial::~NonTrivial | true | 566 | 564 | |
| __va_list_tag::operator= | false | 66 | 66 | operator= |
| __va_list_tag::operator= | false | 72 | 72 | operator= |
| early_return | false | 799 | 799 | early_return |
| early_return | false | 807 | 807 | declaration |
| early_return | false | 812 | 812 | if (...) ... |
| early_return | false | 814 | 814 | x |
| early_return | false | 816 | 816 | (bool)... |
| early_return | false | 820 | 820 | declaration |
| early_return | false | 822 | 822 | return ... |
| early_return | false | 824 | 824 | { ... } |
| early_return | false | 826 | 826 | declaration |
| early_return | false | 831 | 831 | return ... |
| early_return | false | 833 | 833 | { ... } |
| early_return | false | 835 | 835 | inner |
| early_return | false | 837 | 837 | call to inner.~NonTrivial |
| early_return | false | 838 | 838 | before |
| early_return | false | 840 | 840 | call to before.~NonTrivial |
| early_return | false | 841 | 841 | inner |
| early_return | false | 842 | 842 | call to inner.~NonTrivial |
| early_return | false | 843 | 843 | before |
| early_return | false | 844 | 844 | call to before.~NonTrivial |
| early_return | false | 845 | 845 | after |
| early_return | false | 846 | 846 | call to after.~NonTrivial |
| early_return | true | 807 | 812 | |
| early_return | true | 812 | 814 | |
| early_return | true | 814 | 824 | T |
| early_return | true | 814 | 826 | F |
| early_return | true | 820 | 822 | |
| early_return | true | 822 | 841 | |
| early_return | true | 824 | 820 | |
| early_return | true | 826 | 831 | |
| early_return | true | 831 | 845 | |
| early_return | true | 833 | 807 | |
| early_return | true | 835 | 837 | |
| early_return | true | 837 | 826 | |
| early_return | true | 838 | 840 | |
| early_return | true | 840 | 799 | |
| early_return | true | 841 | 842 | |
| early_return | true | 842 | 838 | |
| early_return | true | 843 | 844 | |
| early_return | true | 844 | 799 | |
| early_return | true | 845 | 846 | |
| early_return | true | 846 | 843 | |
| early_throw | false | 749 | 749 | early_throw |
| early_throw | false | 757 | 757 | declaration |
| early_throw | false | 762 | 762 | if (...) ... |
| early_throw | false | 764 | 764 | x |
| early_throw | false | 766 | 766 | (bool)... |
| early_throw | false | 770 | 770 | declaration |
| early_throw | false | 772 | 772 | ExprStmt |
| early_throw | false | 774 | 774 | re-throw exception |
| early_throw | false | 776 | 776 | { ... } |
| early_throw | false | 778 | 778 | declaration |
| early_throw | false | 783 | 783 | return ... |
| early_throw | false | 785 | 785 | { ... } |
| early_throw | false | 787 | 787 | inner |
| early_throw | false | 789 | 789 | call to inner.~NonTrivial |
| early_throw | false | 790 | 790 | before |
| early_throw | false | 792 | 792 | call to before.~NonTrivial |
| early_throw | false | 793 | 793 | inner |
| early_throw | false | 794 | 794 | call to inner.~NonTrivial |
| early_throw | false | 795 | 795 | before |
| early_throw | false | 796 | 796 | call to before.~NonTrivial |
| early_throw | false | 797 | 797 | after |
| early_throw | false | 798 | 798 | call to after.~NonTrivial |
| early_throw | true | 757 | 762 | |
| early_throw | true | 762 | 764 | |
| early_throw | true | 764 | 776 | T |
| early_throw | true | 764 | 778 | F |
| early_throw | true | 770 | 772 | |
| early_throw | true | 772 | 774 | |
| early_throw | true | 774 | 793 | |
| early_throw | true | 776 | 770 | |
| early_throw | true | 778 | 783 | |
| early_throw | true | 783 | 797 | |
| early_throw | true | 785 | 757 | |
| early_throw | true | 787 | 789 | |
| early_throw | true | 789 | 778 | |
| early_throw | true | 790 | 792 | |
| early_throw | true | 792 | 749 | |
| early_throw | true | 793 | 794 | |
| early_throw | true | 794 | 790 | |
| early_throw | true | 795 | 796 | |
| early_throw | true | 796 | 749 | |
| early_throw | true | 797 | 798 | |
| early_throw | true | 798 | 795 | |
| early_return | false | 800 | 800 | early_return |
| early_return | false | 808 | 808 | declaration |
| early_return | false | 813 | 813 | if (...) ... |
| early_return | false | 815 | 815 | x |
| early_return | false | 817 | 817 | (bool)... |
| early_return | false | 821 | 821 | declaration |
| early_return | false | 823 | 823 | return ... |
| early_return | false | 825 | 825 | { ... } |
| early_return | false | 827 | 827 | declaration |
| early_return | false | 832 | 832 | return ... |
| early_return | false | 834 | 834 | { ... } |
| early_return | false | 836 | 836 | before |
| early_return | false | 838 | 838 | call to before.~NonTrivial |
| early_return | false | 839 | 839 | inner |
| early_return | false | 841 | 841 | call to inner.~NonTrivial |
| early_return | false | 842 | 842 | inner |
| early_return | false | 843 | 843 | call to inner.~NonTrivial |
| early_return | false | 844 | 844 | before |
| early_return | false | 845 | 845 | call to before.~NonTrivial |
| early_return | false | 846 | 846 | after |
| early_return | false | 847 | 847 | call to after.~NonTrivial |
| early_return | true | 808 | 813 | |
| early_return | true | 813 | 815 | |
| early_return | true | 815 | 825 | T |
| early_return | true | 815 | 827 | F |
| early_return | true | 821 | 823 | |
| early_return | true | 823 | 839 | |
| early_return | true | 825 | 821 | |
| early_return | true | 827 | 832 | |
| early_return | true | 832 | 846 | |
| early_return | true | 834 | 808 | |
| early_return | true | 836 | 838 | |
| early_return | true | 838 | 800 | |
| early_return | true | 839 | 841 | |
| early_return | true | 841 | 836 | |
| early_return | true | 842 | 843 | |
| early_return | true | 843 | 827 | |
| early_return | true | 844 | 845 | |
| early_return | true | 845 | 800 | |
| early_return | true | 846 | 847 | |
| early_return | true | 847 | 844 | |
| early_throw | false | 750 | 750 | early_throw |
| early_throw | false | 758 | 758 | declaration |
| early_throw | false | 763 | 763 | if (...) ... |
| early_throw | false | 765 | 765 | x |
| early_throw | false | 767 | 767 | (bool)... |
| early_throw | false | 771 | 771 | declaration |
| early_throw | false | 773 | 773 | ExprStmt |
| early_throw | false | 775 | 775 | re-throw exception |
| early_throw | false | 777 | 777 | { ... } |
| early_throw | false | 779 | 779 | declaration |
| early_throw | false | 784 | 784 | return ... |
| early_throw | false | 786 | 786 | { ... } |
| early_throw | false | 788 | 788 | before |
| early_throw | false | 790 | 790 | call to before.~NonTrivial |
| early_throw | false | 791 | 791 | inner |
| early_throw | false | 793 | 793 | call to inner.~NonTrivial |
| early_throw | false | 794 | 794 | inner |
| early_throw | false | 795 | 795 | call to inner.~NonTrivial |
| early_throw | false | 796 | 796 | before |
| early_throw | false | 797 | 797 | call to before.~NonTrivial |
| early_throw | false | 798 | 798 | after |
| early_throw | false | 799 | 799 | call to after.~NonTrivial |
| early_throw | true | 758 | 763 | |
| early_throw | true | 763 | 765 | |
| early_throw | true | 765 | 777 | T |
| early_throw | true | 765 | 779 | F |
| early_throw | true | 771 | 773 | |
| early_throw | true | 773 | 775 | |
| early_throw | true | 775 | 791 | |
| early_throw | true | 777 | 771 | |
| early_throw | true | 779 | 784 | |
| early_throw | true | 784 | 798 | |
| early_throw | true | 786 | 758 | |
| early_throw | true | 788 | 790 | |
| early_throw | true | 790 | 750 | |
| early_throw | true | 791 | 793 | |
| early_throw | true | 793 | 788 | |
| early_throw | true | 794 | 795 | |
| early_throw | true | 795 | 779 | |
| early_throw | true | 796 | 797 | |
| early_throw | true | 797 | 750 | |
| early_throw | true | 798 | 799 | |
| early_throw | true | 799 | 796 | |
| for_decl_bind | false | 153 | 153 | for_decl_bind |
| for_decl_bind | false | 161 | 161 | for(...;...;...) ... |
| for_decl_bind | false | 164 | 164 | call to BoxedInt |
@@ -194,108 +194,108 @@
| for_decl_bind | true | 225 | 219 | |
| for_decl_bind | true | 226 | 227 | |
| for_decl_bind | true | 227 | 182 | |
| for_loop_scope | false | 698 | 698 | for_loop_scope |
| for_loop_scope | false | 706 | 706 | declaration |
| for_loop_scope | false | 711 | 711 | for(...;...;...) ... |
| for_loop_scope | false | 716 | 716 | x |
| for_loop_scope | false | 720 | 720 | 10 |
| for_loop_scope | false | 721 | 721 | ... < ... |
| for_loop_scope | false | 726 | 726 | declaration |
| for_loop_scope | false | 728 | 728 | { ... } |
| for_loop_scope | false | 730 | 730 | declaration |
| for_loop_scope | false | 732 | 732 | x |
| for_loop_scope | false | 734 | 734 | ++ ... |
| for_loop_scope | false | 736 | 736 | return ... |
| for_loop_scope | false | 738 | 738 | { ... } |
| for_loop_scope | false | 740 | 740 | for_scope |
| for_loop_scope | false | 742 | 742 | call to for_scope.~NonTrivial |
| for_loop_scope | false | 743 | 743 | inner_scope |
| for_loop_scope | false | 745 | 745 | call to inner_scope.~NonTrivial |
| for_loop_scope | false | 746 | 746 | outer_scope |
| for_loop_scope | false | 748 | 748 | call to outer_scope.~NonTrivial |
| for_loop_scope | true | 706 | 711 | |
| for_loop_scope | true | 711 | 730 | |
| for_loop_scope | true | 716 | 720 | |
| for_loop_scope | true | 720 | 721 | |
| for_loop_scope | true | 721 | 728 | T |
| for_loop_scope | true | 721 | 740 | F |
| for_loop_scope | true | 726 | 743 | |
| for_loop_scope | true | 728 | 726 | |
| for_loop_scope | true | 730 | 716 | |
| for_loop_scope | true | 732 | 734 | |
| for_loop_scope | true | 734 | 716 | |
| for_loop_scope | true | 736 | 746 | |
| for_loop_scope | true | 738 | 706 | |
| for_loop_scope | true | 740 | 742 | |
| for_loop_scope | true | 742 | 736 | |
| for_loop_scope | true | 743 | 745 | |
| for_loop_scope | true | 745 | 732 | |
| for_loop_scope | true | 746 | 748 | |
| for_loop_scope | true | 748 | 698 | |
| gotos | false | 608 | 608 | gotos |
| gotos | false | 616 | 616 | declaration |
| gotos | false | 621 | 621 | if (...) ... |
| gotos | false | 623 | 623 | x |
| gotos | false | 625 | 625 | (bool)... |
| gotos | false | 626 | 626 | goto ... |
| gotos | false | 628 | 628 | x |
| gotos | false | 630 | 630 | ++ ... |
| gotos | false | 632 | 632 | initializer for y |
| gotos | false | 643 | 643 | declaration |
| gotos | false | 645 | 645 | label ...: |
| gotos | false | 647 | 647 | declaration |
| gotos | false | 649 | 649 | if (...) ... |
| gotos | false | 651 | 651 | y |
| gotos | false | 653 | 653 | (bool)... |
| gotos | false | 654 | 654 | goto ... |
| gotos | false | 656 | 656 | declaration |
| gotos | false | 658 | 658 | { ... } |
| gotos | false | 660 | 660 | label ...: |
| gotos | false | 662 | 662 | ExprStmt |
| gotos | false | 664 | 664 | x |
| gotos | false | 666 | 666 | -- ... |
| gotos | false | 668 | 668 | return ... |
| gotos | false | 670 | 670 | { ... } |
| gotos | false | 672 | 672 | nt2 |
| gotos | false | 674 | 674 | call to nt2.~NonTrivial |
| gotos | false | 675 | 675 | nt3 |
| gotos | false | 676 | 676 | call to nt3.~NonTrivial |
| gotos | false | 677 | 677 | nt2 |
| gotos | false | 678 | 678 | call to nt2.~NonTrivial |
| gotos | false | 679 | 679 | nt1 |
| gotos | false | 681 | 681 | call to nt1.~NonTrivial |
| gotos | true | 616 | 621 | |
| gotos | true | 621 | 623 | |
| gotos | true | 623 | 626 | T |
| gotos | true | 623 | 658 | F |
| gotos | true | 626 | 645 | |
| gotos | true | 628 | 630 | |
| gotos | true | 630 | 645 | |
| gotos | true | 632 | 628 | |
| gotos | true | 643 | 632 | |
| gotos | true | 643 | 645 | |
| gotos | true | 645 | 647 | |
| gotos | true | 647 | 649 | |
| gotos | true | 649 | 651 | |
| gotos | true | 651 | 654 | T |
| gotos | true | 651 | 656 | F |
| gotos | true | 654 | 677 | |
| gotos | true | 656 | 675 | |
| gotos | true | 658 | 643 | |
| gotos | true | 660 | 662 | |
| gotos | true | 662 | 664 | |
| gotos | true | 664 | 666 | |
| gotos | true | 666 | 668 | |
| gotos | true | 668 | 679 | |
| gotos | true | 670 | 616 | |
| gotos | true | 672 | 674 | |
| gotos | true | 674 | 660 | |
| gotos | true | 675 | 676 | |
| gotos | true | 676 | 672 | |
| gotos | true | 677 | 678 | |
| gotos | true | 678 | 660 | |
| gotos | true | 679 | 681 | |
| gotos | true | 681 | 608 | |
| for_loop_scope | false | 699 | 699 | for_loop_scope |
| for_loop_scope | false | 707 | 707 | declaration |
| for_loop_scope | false | 712 | 712 | for(...;...;...) ... |
| for_loop_scope | false | 717 | 717 | x |
| for_loop_scope | false | 721 | 721 | 10 |
| for_loop_scope | false | 722 | 722 | ... < ... |
| for_loop_scope | false | 727 | 727 | declaration |
| for_loop_scope | false | 729 | 729 | { ... } |
| for_loop_scope | false | 731 | 731 | declaration |
| for_loop_scope | false | 733 | 733 | x |
| for_loop_scope | false | 735 | 735 | ++ ... |
| for_loop_scope | false | 737 | 737 | return ... |
| for_loop_scope | false | 739 | 739 | { ... } |
| for_loop_scope | false | 741 | 741 | for_scope |
| for_loop_scope | false | 743 | 743 | call to for_scope.~NonTrivial |
| for_loop_scope | false | 744 | 744 | inner_scope |
| for_loop_scope | false | 746 | 746 | call to inner_scope.~NonTrivial |
| for_loop_scope | false | 747 | 747 | outer_scope |
| for_loop_scope | false | 749 | 749 | call to outer_scope.~NonTrivial |
| for_loop_scope | true | 707 | 712 | |
| for_loop_scope | true | 712 | 731 | |
| for_loop_scope | true | 717 | 721 | |
| for_loop_scope | true | 721 | 722 | |
| for_loop_scope | true | 722 | 729 | T |
| for_loop_scope | true | 722 | 741 | F |
| for_loop_scope | true | 727 | 744 | |
| for_loop_scope | true | 729 | 727 | |
| for_loop_scope | true | 731 | 717 | |
| for_loop_scope | true | 733 | 735 | |
| for_loop_scope | true | 735 | 717 | |
| for_loop_scope | true | 737 | 747 | |
| for_loop_scope | true | 739 | 707 | |
| for_loop_scope | true | 741 | 743 | |
| for_loop_scope | true | 743 | 737 | |
| for_loop_scope | true | 744 | 746 | |
| for_loop_scope | true | 746 | 733 | |
| for_loop_scope | true | 747 | 749 | |
| for_loop_scope | true | 749 | 699 | |
| gotos | false | 609 | 609 | gotos |
| gotos | false | 617 | 617 | declaration |
| gotos | false | 622 | 622 | if (...) ... |
| gotos | false | 624 | 624 | x |
| gotos | false | 626 | 626 | (bool)... |
| gotos | false | 627 | 627 | goto ... |
| gotos | false | 629 | 629 | x |
| gotos | false | 631 | 631 | ++ ... |
| gotos | false | 633 | 633 | initializer for y |
| gotos | false | 644 | 644 | declaration |
| gotos | false | 646 | 646 | label ...: |
| gotos | false | 648 | 648 | declaration |
| gotos | false | 650 | 650 | if (...) ... |
| gotos | false | 652 | 652 | y |
| gotos | false | 654 | 654 | (bool)... |
| gotos | false | 655 | 655 | goto ... |
| gotos | false | 657 | 657 | declaration |
| gotos | false | 659 | 659 | { ... } |
| gotos | false | 661 | 661 | label ...: |
| gotos | false | 663 | 663 | ExprStmt |
| gotos | false | 665 | 665 | x |
| gotos | false | 667 | 667 | -- ... |
| gotos | false | 669 | 669 | return ... |
| gotos | false | 671 | 671 | { ... } |
| gotos | false | 673 | 673 | nt2 |
| gotos | false | 675 | 675 | call to nt2.~NonTrivial |
| gotos | false | 676 | 676 | nt2 |
| gotos | false | 677 | 677 | call to nt2.~NonTrivial |
| gotos | false | 678 | 678 | nt3 |
| gotos | false | 679 | 679 | call to nt3.~NonTrivial |
| gotos | false | 680 | 680 | nt1 |
| gotos | false | 682 | 682 | call to nt1.~NonTrivial |
| gotos | true | 617 | 622 | |
| gotos | true | 622 | 624 | |
| gotos | true | 624 | 627 | T |
| gotos | true | 624 | 659 | F |
| gotos | true | 627 | 646 | |
| gotos | true | 629 | 631 | |
| gotos | true | 631 | 646 | |
| gotos | true | 633 | 629 | |
| gotos | true | 644 | 633 | |
| gotos | true | 644 | 646 | |
| gotos | true | 646 | 648 | |
| gotos | true | 648 | 650 | |
| gotos | true | 650 | 652 | |
| gotos | true | 652 | 655 | T |
| gotos | true | 652 | 657 | F |
| gotos | true | 655 | 673 | |
| gotos | true | 657 | 678 | |
| gotos | true | 659 | 644 | |
| gotos | true | 661 | 663 | |
| gotos | true | 663 | 665 | |
| gotos | true | 665 | 667 | |
| gotos | true | 667 | 669 | |
| gotos | true | 669 | 680 | |
| gotos | true | 671 | 617 | |
| gotos | true | 673 | 675 | |
| gotos | true | 675 | 661 | |
| gotos | true | 676 | 677 | |
| gotos | true | 677 | 661 | |
| gotos | true | 678 | 679 | |
| gotos | true | 679 | 676 | |
| gotos | true | 680 | 682 | |
| gotos | true | 682 | 609 | |
| if_decl_bind | false | 375 | 375 | if_decl_bind |
| if_decl_bind | false | 383 | 383 | if (...) ... |
| if_decl_bind | false | 386 | 386 | call to operator int |
@@ -350,45 +350,45 @@
| if_decl_bind | true | 435 | 383 | |
| if_decl_bind | true | 437 | 439 | |
| if_decl_bind | true | 439 | 424 | |
| never_destructs | false | 682 | 682 | never_destructs |
| never_destructs | false | 687 | 687 | declaration |
| never_destructs | false | 692 | 692 | label ...: |
| never_destructs | false | 694 | 694 | goto ... |
| never_destructs | false | 696 | 696 | { ... } |
| never_destructs | true | 687 | 692 | |
| never_destructs | true | 692 | 694 | |
| never_destructs | true | 694 | 692 | |
| never_destructs | true | 696 | 687 | |
| never_destructs | false | 683 | 683 | never_destructs |
| never_destructs | false | 688 | 688 | declaration |
| never_destructs | false | 693 | 693 | label ...: |
| never_destructs | false | 695 | 695 | goto ... |
| never_destructs | false | 697 | 697 | { ... } |
| never_destructs | true | 688 | 693 | |
| never_destructs | true | 693 | 695 | |
| never_destructs | true | 695 | 693 | |
| never_destructs | true | 697 | 688 | |
| operator delete | false | 476 | 476 | operator delete |
| operator new | false | 499 | 499 | operator new |
| simple | false | 871 | 871 | simple |
| simple | false | 876 | 876 | declaration |
| simple | false | 881 | 881 | return ... |
| simple | false | 883 | 883 | { ... } |
| simple | false | 885 | 885 | nt |
| simple | false | 887 | 887 | call to nt.~NonTrivial |
| simple | true | 876 | 881 | |
| simple | true | 881 | 885 | |
| simple | true | 883 | 876 | |
| simple | true | 885 | 887 | |
| simple | true | 887 | 871 | |
| simple2 | false | 847 | 847 | simple2 |
| simple2 | false | 852 | 852 | declaration |
| simple2 | false | 857 | 857 | declaration |
| simple2 | false | 862 | 862 | return ... |
| simple2 | false | 864 | 864 | { ... } |
| simple2 | false | 866 | 866 | one |
| simple2 | false | 868 | 868 | call to one.~NonTrivial |
| simple2 | false | 869 | 869 | two |
| simple2 | false | 870 | 870 | call to two.~NonTrivial |
| simple2 | true | 852 | 857 | |
| simple2 | true | 857 | 862 | |
| simple2 | true | 862 | 869 | |
| simple2 | true | 864 | 852 | |
| simple2 | true | 866 | 868 | |
| simple2 | true | 868 | 847 | |
| simple2 | true | 869 | 870 | |
| simple2 | true | 870 | 866 | |
| simple | false | 872 | 872 | simple |
| simple | false | 877 | 877 | declaration |
| simple | false | 882 | 882 | return ... |
| simple | false | 884 | 884 | { ... } |
| simple | false | 886 | 886 | nt |
| simple | false | 888 | 888 | call to nt.~NonTrivial |
| simple | true | 877 | 882 | |
| simple | true | 882 | 886 | |
| simple | true | 884 | 877 | |
| simple | true | 886 | 888 | |
| simple | true | 888 | 872 | |
| simple2 | false | 848 | 848 | simple2 |
| simple2 | false | 853 | 853 | declaration |
| simple2 | false | 858 | 858 | declaration |
| simple2 | false | 863 | 863 | return ... |
| simple2 | false | 865 | 865 | { ... } |
| simple2 | false | 867 | 867 | one |
| simple2 | false | 869 | 869 | call to one.~NonTrivial |
| simple2 | false | 870 | 870 | two |
| simple2 | false | 871 | 871 | call to two.~NonTrivial |
| simple2 | true | 853 | 858 | |
| simple2 | true | 858 | 863 | |
| simple2 | true | 863 | 870 | |
| simple2 | true | 865 | 853 | |
| simple2 | true | 867 | 869 | |
| simple2 | true | 869 | 848 | |
| simple2 | true | 870 | 871 | |
| simple2 | true | 871 | 867 | |
| switch_decl_bind | false | 276 | 276 | switch_decl_bind |
| switch_decl_bind | false | 284 | 284 | switch (...) ... |
| switch_decl_bind | false | 287 | 287 | call to operator int |
@@ -444,21 +444,21 @@
| switch_decl_bind | true | 310 | 313 | |
| switch_decl_bind | true | 313 | 315 | |
| switch_decl_bind | true | 315 | 317 | |
| switch_decl_bind | true | 317 | 371 | |
| switch_decl_bind | true | 317 | 368 | |
| switch_decl_bind | true | 319 | 324 | |
| switch_decl_bind | true | 324 | 326 | |
| switch_decl_bind | true | 326 | 328 | |
| switch_decl_bind | true | 328 | 330 | |
| switch_decl_bind | true | 330 | 332 | |
| switch_decl_bind | true | 332 | 334 | |
| switch_decl_bind | true | 334 | 373 | |
| switch_decl_bind | true | 334 | 371 | |
| switch_decl_bind | true | 336 | 338 | |
| switch_decl_bind | true | 338 | 340 | |
| switch_decl_bind | true | 340 | 342 | |
| switch_decl_bind | true | 342 | 344 | |
| switch_decl_bind | true | 344 | 348 | |
| switch_decl_bind | true | 348 | 349 | |
| switch_decl_bind | true | 349 | 368 | |
| switch_decl_bind | true | 349 | 373 | |
| switch_decl_bind | true | 351 | 300 | |
| switch_decl_bind | true | 351 | 319 | |
| switch_decl_bind | true | 351 | 336 | |
@@ -501,10 +501,11 @@
| while_decl_bind | true | 241 | 251 | |
| while_decl_bind | true | 243 | 241 | |
| while_decl_bind | true | 251 | 259 | T |
| while_decl_bind | true | 251 | 271 | F |
| while_decl_bind | true | 251 | 274 | F |
| while_decl_bind | true | 253 | 255 | |
| while_decl_bind | true | 255 | 257 | |
| while_decl_bind | true | 257 | 274 | |
| while_decl_bind | true | 257 | 243 | |
| while_decl_bind | true | 257 | 271 | |
| while_decl_bind | true | 259 | 253 | |
| while_decl_bind | true | 261 | 263 | |
| while_decl_bind | true | 263 | 265 | |
@@ -512,6 +513,5 @@
| while_decl_bind | true | 267 | 228 | |
| while_decl_bind | true | 269 | 236 | |
| while_decl_bind | true | 271 | 273 | |
| while_decl_bind | true | 273 | 261 | |
| while_decl_bind | true | 274 | 275 | |
| while_decl_bind | true | 275 | 243 | |
| while_decl_bind | true | 275 | 261 | |

View File

@@ -77,7 +77,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// "json.net"
/// }
/// </summary>
private void AddPackageDependencies(JObject json)
private void AddPackageDependencies(JObject json, string jsonPath)
{
// If there is more than one framework we need to pick just one.
// To ensure stability we pick one based on the lexicographic order of
@@ -91,7 +91,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (references is null)
{
logger.LogDebug("No references found in the targets section in the assets file.");
logger.LogDebug($"No references found in the targets section in '{jsonPath}'");
return;
}
@@ -154,7 +154,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// "microsoft.netcore.app.ref"
/// }
/// </summary>
private void AddFrameworkDependencies(JObject json)
private void AddFrameworkDependencies(JObject json, string jsonPath)
{
var frameworks = json
@@ -163,7 +163,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (frameworks is null)
{
logger.LogDebug("No framework section in assets.json.");
logger.LogDebug($"No framework section in '{jsonPath}'.");
return;
}
@@ -177,7 +177,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (references is null)
{
logger.LogDebug("No framework references in assets.json.");
logger.LogDebug($"No framework references in '{jsonPath}'.");
return;
}
@@ -196,8 +196,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
try
{
var obj = JObject.Parse(json);
AddPackageDependencies(obj);
AddFrameworkDependencies(obj);
AddPackageDependencies(obj, json);
AddFrameworkDependencies(obj, json);
return true;
}
catch (Exception e)

View File

@@ -94,7 +94,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
public HashSet<AssemblyLookupLocation> Restore()
{
var assemblyLookupLocations = new HashSet<AssemblyLookupLocation>();
var checkNugetFeedResponsiveness = EnvironmentVariables.GetBoolean(EnvironmentVariableNames.CheckNugetFeedResponsiveness);
var checkNugetFeedResponsiveness = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.CheckNugetFeedResponsiveness);
logger.LogInfo($"Checking NuGet feed responsiveness: {checkNugetFeedResponsiveness}");
compilationInfoContainer.CompilationInfos.Add(("NuGet feed responsiveness checked", checkNugetFeedResponsiveness ? "1" : "0"));
try
{
if (checkNugetFeedResponsiveness && !CheckFeeds())

View File

@@ -20,17 +20,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
protected override bool IsEnabled()
{
var webViewExtractionOption = Environment.GetEnvironmentVariable(EnvironmentVariableNames.WebViewGeneration);
if (webViewExtractionOption == null ||
bool.TryParse(webViewExtractionOption, out var shouldExtractWebViews) &&
shouldExtractWebViews)
{
compilationInfoContainer.CompilationInfos.Add(("WebView extraction enabled", "1"));
return true;
}
compilationInfoContainer.CompilationInfos.Add(("WebView extraction enabled", "0"));
return false;
var webViewExtractionOption = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.WebViewGeneration);
compilationInfoContainer.CompilationInfos.Add(("WebView extraction enabled", webViewExtractionOption ? "1" : "0"));
return webViewExtractionOption;
}
protected override ICollection<string> AdditionalFiles => fileProvider.RazorViews;

View File

@@ -29,6 +29,19 @@ namespace Semmle.Util
return threads;
}
public static bool GetBooleanOptOut(string name)
{
var env = Environment.GetEnvironmentVariable(name);
if (env == null ||
bool.TryParse(env, out var value) &&
value)
{
return true;
}
return false;
}
public static bool GetBoolean(string name)
{
var env = Environment.GetEnvironmentVariable(name);

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
| All Nuget feeds reachable | 1.0 |
| Failed project restore with package source error | 0.0 |
| Failed solution restore with package source error | 0.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Resource extraction enabled | 1.0 |
| Restored .NET framework variants | 1.0 |

View File

@@ -1,6 +1,8 @@
| All Nuget feeds reachable | 1.0 |
| Failed project restore with package source error | 1.0 |
| Failed solution restore with package source error | 0.0 |
| Fallback nuget restore | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Resolved assembly conflicts | 7.0 |
| Resource extraction enabled | 0.0 |

View File

@@ -1,6 +1,7 @@
| All Nuget feeds reachable | 0.0 |
| Fallback nuget restore | 1.0 |
| Inherited Nuget feed count | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Resolved assembly conflicts | 7.0 |
| Resource extraction enabled | 0.0 |

View File

@@ -2,7 +2,7 @@ from create_database_utils import *
from diagnostics_test_utils import *
import os
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # Enable NuGet feed check
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # Nuget feed check is enabled by default
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_TIMEOUT"] = "1" # 1ms, the GET request should fail with such short timeout
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_LIMIT"] = "1" # Limit the count of checks to 1
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_EXCLUDED"] = "https://abc.de:8000/packages/" # Exclude this feed from check

View File

@@ -1,4 +1,6 @@
extensions:
# Make sure that the extensible model predicates have at least one definition
# to avoid errors about undefined extensionals.
- addsTo:
pack: codeql/csharp-all
extensible: sourceModel

View File

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

View File

@@ -51,8 +51,6 @@ class TopLevelExprParent extends Element, @top_level_expr_parent {
final Expr getAChildExpr() { result = this.getChildExpr(_) }
}
private predicate hasNoSourceLocation(Element e) { not e.getALocation() instanceof SourceLocation }
/** INTERNAL: Do not use. */
Expr getExpressionBody(Callable c) {
result = c.getAChildExpr() and
@@ -67,17 +65,46 @@ private ControlFlowElement getBody(Callable c) {
result = getStatementBody(c)
}
pragma[nomagic]
private SourceLocation getASourceLocation(Element e) {
result = e.getALocation().(SourceLocation) and
not exists(e.getALocation().(SourceLocation).getMappedLocation())
or
result = e.getALocation().(SourceLocation).getMappedLocation()
}
pragma[nomagic]
private predicate hasNoSourceLocation(Element e) { not exists(getASourceLocation(e)) }
pragma[nomagic]
private Location getFirstSourceLocation(Element e) {
result =
min(Location l, string filepath, int startline, int startcolumn, int endline, int endcolumn |
l = getASourceLocation(e) and
l.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
l order by filepath, startline, startcolumn, endline, endcolumn
)
}
cached
private module Cached {
cached
Location bestLocation(Element e) {
result = e.getALocation().(SourceLocation) and
not exists(e.getALocation().(SourceLocation).getMappedLocation())
or
result = e.getALocation().(SourceLocation).getMappedLocation()
(
if e.(Modifiable).isPartial() or e instanceof Namespace
then result = getASourceLocation(e)
else result = getFirstSourceLocation(e)
)
or
hasNoSourceLocation(e) and
result = min(Location l | l = e.getALocation() | l order by l.getFile().toString())
result =
min(Location l, string filepath |
l = e.getALocation() and
l.hasLocationInfo(filepath, _, _, _, _)
|
l order by filepath
)
or
not exists(e.getALocation()) and
result instanceof EmptyLocation

View File

@@ -63,7 +63,7 @@ class EmptyLocation extends Location {
*/
class SourceLocation extends Location, @location_default {
/** Gets the location that takes into account `#line` directives, if any. */
Location getMappedLocation() {
SourceLocation getMappedLocation() {
locations_mapped(this, result) and
not exists(LineDirective l | l.getALocation() = this)
}

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.codedom.Compiler
private import semmle.code.csharp.security.Sanitizers
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for user input treated as code vulnerabilities.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for user input treated as code vulnerabilities.

View File

@@ -6,6 +6,7 @@
import csharp
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.controlflow.BasicBlocks
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.Net
@@ -14,12 +15,12 @@ private import semmle.code.csharp.security.SensitiveActions
/**
* A data flow source for user-controlled bypass of sensitive method.
*/
abstract class Source extends DataFlow::Node { }
abstract class Source extends ApiSourceNode { }
/**
* A data flow sink for user-controlled bypass of sensitive method.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/** Gets the 'MethodCall' which is considered sensitive. */
abstract MethodCall getSensitiveMethodCall();
}

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
private import semmle.code.csharp.security.PrivateData
@@ -15,7 +16,7 @@ abstract class Source extends DataFlow::ExprNode { }
/**
* A data flow sink for private information flowing unencrypted to an external location.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for private information flowing unencrypted to an external location.

View File

@@ -9,6 +9,7 @@ private import semmle.code.csharp.frameworks.Moq
private import semmle.code.csharp.frameworks.system.web.Security
private import semmle.code.csharp.frameworks.system.security.cryptography.X509Certificates
private import semmle.code.csharp.frameworks.Test
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
/**
* A data flow source for hard coded credentials.
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::ExprNode { }
/**
* A data flow sink for hard coded credentials.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/**
* Gets a description of this sink, including a placeholder for the sink and a placeholder for
* the supplementary element.

View File

@@ -4,6 +4,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.DirectoryServices
private import semmle.code.csharp.frameworks.system.directoryservices.Protocols
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for unvalidated user input that is used to construct LDAP queries.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for unvalidated user input that is used to construct LDAP queries.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in log entries.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in log entries.

View File

@@ -4,6 +4,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.Xml
private import semmle.code.csharp.security.Sanitizers
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
* A data flow sink for untrusted user input processed as XML without validation against a known
* schema.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/** Gets a string describing the reason why this is a sink. */
abstract string getReason();
}

View File

@@ -5,6 +5,7 @@
import csharp
private import semmle.code.csharp.dataflow.DataFlow2
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
private import semmle.code.csharp.security.Sanitizers
@@ -17,7 +18,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in dangerous regular expression operations.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in dangerous regular expression operations.

View File

@@ -4,6 +4,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
private import semmle.code.csharp.security.Sanitizers
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used to construct regular expressions.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used to construct regular expressions.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.Data
private import semmle.code.csharp.security.Sanitizers
@@ -15,7 +16,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in resource descriptors.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in resource descriptors.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.Sql
private import semmle.code.csharp.security.Sanitizers
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A sink for SQL injection vulnerabilities.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for SQL injection vulnerabilities.

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