Compare commits

...

358 Commits

Author SHA1 Message Date
Dave Bartolomeo
b7f0b7afb5 Merge pull request #16489 from github/release-prep/2.17.3
Release preparation for version 2.17.3
2024-05-14 15:43:46 -04:00
github-actions[bot]
100166fa53 Release preparation for version 2.17.3 2024-05-14 19:23:18 +00:00
Chris Smowton
d76182b945 Merge pull request #16468 from smowton/smowton/admin/add-buildless-timeout-tests
Java: add test cases for Maven and Gradle stalling in buildless mode
2024-05-14 19:13:03 +01:00
Chris Smowton
829707528b Merge pull request #16488 from smowton/smowton/admin/document-test-servers
Java: Add comments to tests that spawn an HTTP/S server
2024-05-14 18:11:20 +01:00
Chris Smowton
cf134331a9 Java: Add comments to tests that spawn an HTTP/S server 2024-05-14 17:48:35 +01:00
Chris Smowton
61cd93fcf3 Switch to a different black-hole IP, because Windows blocks 240.0.0.0/24 2024-05-14 17:36:50 +01:00
Chris Smowton
e699b18928 Java: add test cases for Maven and Gradle stalling in buildless mode 2024-05-14 17:36:49 +01:00
Chris Smowton
1b1367eec0 Merge pull request #16479 from smowton/smowton/admin/test-java-trust-store-inheritence
Java: Add test case for a custom Java trust store
2024-05-14 17:35:26 +01:00
Chris Smowton
8814e6e2bd Replace deprecated ssl.wrap_socket method 2024-05-14 15:14:27 +01:00
Chuan-kai Lin
99335e5f29 Merge pull request #16421 from github/cklin/java-entities-reorder
Java: Use entities in reorder directives
2024-05-14 06:03:52 -07:00
Joe Farebrother
027e5e7291 Merge pull request #16300 from joefarebrother/python-pyramid
Python: Model the Pyramid framework
2024-05-14 13:24:19 +01:00
Joe Farebrother
904799b674 Merge pull request #16105 from joefarebrother/python-promote-header-injection
Python: Promote Header Injection query from experimental
2024-05-14 13:23:58 +01:00
Michael Nebel
79c6834aa3 Merge pull request #16374 from michaelnebel/java/narrowsuperimpl
Java: Improve finding best type for models and lifting.
2024-05-14 13:12:04 +02:00
Óscar San José
e65a62c727 Merge pull request #16485 from github/oscarsj/fix-lfs-probe-auth-in-cs
make sure GITHUB_TOKEN exists and is not empty before using it in auth headers
2024-05-14 11:49:20 +02:00
Óscar San José
9105faa3fd make sure GITHUB_TOKEN exists and is not empty before using it in auth headers 2024-05-14 11:22:07 +02:00
Óscar San José
faa2dcee24 test GITHUB_TOKEN non-emptyness before using it in auth headers 2024-05-14 11:18:18 +02:00
Joe Farebrother
a62ce4c51d Merge pull request #16461 from joefarebrother/csharp-missing-cwe-metadata
C#: Add missing CWE tags
2024-05-14 09:32:06 +01:00
Óscar San José
5b572a2c2a make GITHUB_TOKEN in lfs_probe a fallback rather than an override 2024-05-14 10:24:02 +02:00
Anders Schack-Mulligen
ed0717af96 Merge pull request #16478 from aschackmull/java/hasqualifiedname
Java: Clean up some instances of getQualifiedName.
2024-05-14 09:19:25 +02:00
Joe Farebrother
513a319149 Change cwe to 348 2024-05-13 22:38:47 +01:00
Chuan-kai Lin
b34fb7c26b Merge pull request #16423 from github/cklin/python-entities-reorder
Python: Use entities in reorder directives
2024-05-13 10:26:55 -07:00
Chuan-kai Lin
1758a1e04b Merge pull request #16422 from github/cklin/javascript-entities-reorder
JS: Use entities in reorder directives
2024-05-13 10:26:41 -07:00
Chuan-kai Lin
9456eaf5d3 Merge pull request #16420 from github/cklin/go-entities-reorder
Go: Use entities in reorder directives
2024-05-13 10:26:04 -07:00
Chuan-kai Lin
372746ffd4 Merge pull request #16419 from github/cklin/csharp-entities-reorder
C#: Use entities in reorder directives
2024-05-13 10:25:50 -07:00
Chris Smowton
10e1bfcee5 Add test case for a custom Java trust store 2024-05-13 12:43:06 +01:00
Anders Schack-Mulligen
76e740bc1d Java: Clean up some instances of getQualifiedName. 2024-05-13 13:06:44 +02:00
Paolo Tranquilli
5eaaf02bf5 Merge pull request #16472 from github/redsun82/go-pre-commit
Go: disable pre-commit hook
2024-05-13 09:49:40 +02:00
Paolo Tranquilli
f125e732b0 Go: disable pre-commit hook 2024-05-13 09:27:35 +02:00
Paolo Tranquilli
c30ca4d9f6 Merge pull request #16398 from github/redsun82/go-make
Go: update `make` and CI to use `bazel`
2024-05-13 08:37:52 +02:00
Erik Krogh Kristensen
0d814e0e20 Merge pull request #16220 from erik-krogh/domainAnc
Go: Add an example specific to domain names in missing-regexp-anchor
2024-05-11 07:52:13 +02:00
Erik Krogh Kristensen
462e564c19 apply suggestion from code review
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-05-10 18:59:55 +02:00
Ian Lynagh
e7092b403b Merge pull request #16401 from igfoo/igfoo/vars
Java/Kotlin: Remove support for some deprecated environment variables
2024-05-10 13:37:55 +01:00
Erik Krogh Kristensen
bcddef8f32 Merge pull request #16131 from erik-krogh/cpp-path
C++: Improve the cpp/path-injection qhelp
2024-05-09 22:21:51 +02:00
Owen Mansel-Chan
e721399eec Merge pull request #16464 from owen-mc/go/fix-broken-test
Go: Fix test expectations
2024-05-09 16:46:04 +01:00
Owen Mansel-Chan
674e65e134 Fix test expectations 2024-05-09 16:26:30 +01:00
Ian Lynagh
4d54c09a6f Java: Add changenote for dropping support for some old variables 2024-05-09 15:59:47 +01:00
Ian Lynagh
b5d6bb9097 Kotlin: Remove unused var SEMMLE_PLATFORM_TOOLS 2024-05-09 15:59:47 +01:00
Ian Lynagh
cfc419b639 Kotlin: Remove unused ODASA_HOME variable 2024-05-09 15:59:47 +01:00
Ian Lynagh
304ad33837 Kotlin: Remove unused ODASA_TOOLS variable 2024-05-09 15:59:47 +01:00
Ian Lynagh
231918f612 Kotlin: Remove redundant variable ODASA_JAVA_LAYOUT 2024-05-09 15:59:47 +01:00
Owen Mansel-Chan
526204dc43 Merge pull request #16458 from owen-mc/go/fix-mad-for-builtin-functions
Go: fix `hasQualifiedName` and models-as-data for built-in functions
2024-05-09 15:06:07 +01:00
Joe Farebrother
20a1e22c44 Add missing CWE tags 2024-05-09 10:33:48 +01:00
Jeroen Ketema
4dfcdbccd7 Merge pull request #16459 from jketema/handler-fix
C++: Fix destructor translation for handlers
2024-05-09 10:23:07 +02:00
Sarita Iyer
aab5da0435 Merge pull request #16320 from github/subatoi/deprecate-codeql-for-vs-code
[8th May 2024] Add deprecation notices to CodeQL for VS Code documentation
2024-05-08 17:00:42 -04:00
Jeroen Ketema
9e09c5a6cf C++: Fix copy and paste error in comment 2024-05-08 22:11:19 +02:00
Owen Mansel-Chan
279b2c7a95 Merge pull request #16457 from owen-mc/go/fix-implicitvarargsslice-type
Go: Fix `getType` on `ImplicitVarArgsSlice`
2024-05-08 20:52:01 +01:00
erik-krogh
811c175556 add example for domain names with sub-domains to missing-regexp-anchor 2024-05-08 20:50:43 +02:00
erik-krogh
a51d24cbab apply suggestions from code review, and the examples to the test 2024-05-08 19:34:50 +02:00
Jeroen Ketema
d68d2cca41 C++: Fix destructor translation for handlers 2024-05-08 19:26:56 +02:00
Jeroen Ketema
0cbedfb28c Merge pull request #16455 from jketema/if-fix
C++: Ensure destructors for ifs are called after both branches and for both if and constexpr if
2024-05-08 19:15:28 +02:00
Geoffrey White
49aba25852 Merge pull request #16445 from geoffw0/qhelp4
C++: Improve qhelp for DoubleFree.
2024-05-08 18:02:12 +01:00
Geoffrey White
53d4a10108 Update cpp/ql/src/Critical/DoubleFree.qhelp
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-05-08 17:15:08 +01:00
Mathias Vorreiter Pedersen
59fb9cc862 Merge pull request #16299 from MathiasVP/remove-base-address-as-ipa-key
C++: Remove an unnecessary column
2024-05-08 16:43:30 +01:00
Owen Mansel-Chan
4f10cb5fa0 Local flow tests: do not list summary models
This is so that when we don't change the test results every time we add
a summary model for a built-in function.
2024-05-08 16:13:37 +01:00
Owen Mansel-Chan
57ff30c5f3 Update tests: built-in models now work 2024-05-08 16:07:02 +01:00
Owen Mansel-Chan
1ccea884ff Add change note 2024-05-08 15:37:25 +01:00
Owen Mansel-Chan
f6f594e4b5 parse empty string as package name 2024-05-08 15:33:19 +01:00
Owen Mansel-Chan
fb74a2a170 Use "" in qualified name for entities without a package 2024-05-08 15:33:19 +01:00
Owen Mansel-Chan
4d42a88c3c Add change note 2024-05-08 15:31:22 +01:00
Owen Mansel-Chan
9842445b52 Fix getType on ImplicitVarArgsSlice
It was not defined for built-in functions or for functions called via
a function variable.
2024-05-08 15:22:27 +01:00
Rasmus Wriedt Larsen
694b3b0fce Merge pull request #16452 from RasmusWL/fix-warning
misc: Fix docstring warning
2024-05-08 16:07:10 +02:00
Michael B. Gale
8cba06a25c Merge pull request #16454 from github/mbg/go/fix/shadowed-variable 2024-05-08 14:13:18 +01:00
Geoffrey White
088f8297b6 C++: Use nullptr. 2024-05-08 14:04:21 +01:00
Joe Farebrother
ab23d0ad23 Merge branch 'main' into python-promote-header-injection 2024-05-08 13:49:00 +01:00
Jeroen Ketema
1a53b923a6 C++: Ensure destructors for ifs are called after both branches 2024-05-08 14:48:28 +02:00
Michael Nebel
64145cf181 Java: Make it evident that we print signature of the lifted callable. 2024-05-08 14:42:53 +02:00
Michael Nebel
f00ad7c0e7 C#/Java: Invert api filtering logic. 2024-05-08 14:42:53 +02:00
Michael Nebel
5e2e224c9c Java: Updated expected test output. 2024-05-08 14:42:53 +02:00
Michael Nebel
e8120afef9 Java: Improve super implementation and ensure that lift produces a result. 2024-05-08 14:42:52 +02:00
Paolo Tranquilli
e359744b8b Go: bring back qhelp in action 2024-05-08 14:31:00 +02:00
Michael B. Gale
896fb87d1d Go: Fix err being shadowed in RunListWithEnv 2024-05-08 13:29:28 +01:00
Michael B. Gale
724d026238 Go: Move go list functions to toolchain package 2024-05-08 13:29:28 +01:00
Jeroen Ketema
52db1c1253 C++: Introduce abstract class to share code between if and constexpr if 2024-05-08 14:16:19 +02:00
Jeroen Ketema
fa06d88642 C++: Add forgotten getLastChild to TranslatedConstExprIfStmt 2024-05-08 14:07:29 +02:00
Rasmus Wriedt Larsen
24f8b5f203 misc: Fix docstring warning
When using a sufficiently new version of Python, it will give a warning
about the escape sequence `\_` in `¯\_(ツ)_/¯` not being a valid escape
:D fix is to make the docstring a raw string.

Thanks @owen-mc
2024-05-08 13:56:11 +02: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
2a40a2a57f Java: Add some inheritance test cases for the model generator and updated expected test output. 2024-05-08 13:01:41 +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
3fd6bc9b5c C++: Fix qhelp format. 2024-05-08 11:46:07 +01:00
Geoffrey White
486226814a C++: Add a second example. 2024-05-08 11:40:29 +01:00
Paolo Tranquilli
12c28f3f68 Go: reorganize CI steps 2024-05-08 12:32:57 +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
Paolo Tranquilli
5b1b30a171 Apply suggestions from code review
Co-authored-by: Michael B. Gale <mbg@github.com>
2024-05-08 12:23:16 +02: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
Mathias Vorreiter Pedersen
65645821be C++: Remove the 'BaseSourceVariableInstruction' column as it's functionally determined by the address column. 2024-05-08 10:00:48 +01: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
3989717878 Merge branch 'main' into cpp-path 2024-05-07 23:01:52 +02:00
erik-krogh
336c7de643 updates based on review 2024-05-07 22:58:49 +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
Geoffrey White
575b66a054 C++: Clarify the recommendation and example. 2024-05-07 16:52:50 +01:00
Geoffrey White
dd95a2abab C++: Move qhelp. 2024-05-07 16:35:21 +01: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
Ben Ahmady
c529988b43 Update README.md
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2024-05-07 13:09:08 +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
Joe Farebrother
efda63d37a Update test output 2024-05-07 10:49:55 +01: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
Joe Farebrother
0f7325ec68 Rename test directory and add comment to clarity on the purpose of splitting them. 2024-05-07 09:40:55 +01: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
bbdc2752ac Merge branch 'main' into redsun82/go-make 2024-05-06 17:43:48 +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
e71d038d7f Go: specify Go runtime version in actions 2024-05-06 14:57:24 +02:00
Paolo Tranquilli
c123513311 Go: bring back test action
This reverts commit 9055d9567a.
2024-05-06 14:56:57 +02:00
Paolo Tranquilli
bab2dd4427 Go: bring back make and CI changes
This reverts commit 12b9b805e2.
2024-05-06 14:56:21 +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
Chuan-kai Lin
535e6db40f Python: Use entities in reorder directives 2024-05-03 11:17:41 -07:00
Chuan-kai Lin
9b51e0e0ee JS: Use entities in reorder directives 2024-05-03 11:17:13 -07:00
Chuan-kai Lin
30b5d5092d Java: Use entities in reorder directives 2024-05-03 11:16:31 -07:00
Chuan-kai Lin
1dd3a0fd76 Go: Use entities in reorder directives 2024-05-03 11:16:08 -07:00
Chuan-kai Lin
077a2e3479 C#: Use entities in reorder directives 2024-05-03 11:15:42 -07: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
Felicity Chapman
54793cfa01 Update a couple of reusables 2024-05-02 12:52:43 +01:00
Tamas Vajk
d909f2bc4f Fix expected test output 2024-05-02 13:32:01 +02:00
Felicity Chapman
7f27127301 Update docs/codeql/reusables/vs-code-deprecation-note.rst 2024-05-02 12:02:09 +01: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
Felicity Chapman
6eb07a7a7e Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-05-02 11:05:39 +01: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
Joe Farebrother
fd55713006 add changenote 2024-04-30 18:17:18 +01:00
Joe Farebrother
c6372d5822 Fix qldoc and remove PotentialViewCallable class 2024-04-30 18:13:06 +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
Joe Farebrother
4f22b91e73 Add tests for cases not yet supported 2024-04-30 15:20:09 +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
Joe Farebrother
ba054bd428 Manually specify subclasses for redirect models 2024-04-30 14:33:46 +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
Joe Farebrother
7df8b1ba51 Don't rely on specific parameter names, add qldoc 2024-04-30 09:45:11 +01: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
Joe Farebrother
2a0459838b Add models for responses 2024-04-25 15:55:59 +01:00
Joe Farebrother
86d1e5b646 Add additional type tracking for request attributes 2024-04-25 13:58:36 +01:00
Ben Ahmady
be9009d653 Use clearer filename 2024-04-25 08:16:48 +00:00
Ben Ahmady
037211c4a4 Add formatting fixes 2024-04-25 08:10:27 +00:00
Ben Ahmady
8cba276b87 Deprecate the CodeQL for VS Code docs in favour of docs.github.com version 2024-04-25 07:59:33 +00: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
Joe Farebrother
53f69d9966 Reduce query tests with cases covered by concept tests 2024-04-24 14:05:42 +01:00
Joe Farebrother
8fb2faa89b Add additional info to concept tests 2024-04-24 14:05:41 +01:00
Joe Farebrother
2b935e575a Add concept tests + fix typo 2024-04-24 14:05:41 +01:00
Joe Farebrother
ec4c820391 Fix deprecation 2024-04-24 14:05:41 +01:00
Joe Farebrother
1dce2eb325 Rename to response splitting 2024-04-24 14:05:40 +01:00
Joe Farebrother
49e5f8a1a5 Add tests for instances of the header write concept 2024-04-24 14:05:40 +01:00
Joe Farebrother
f3b27d611a Add test case for validated wsgiref servers + fix typo 2024-04-24 14:05:40 +01:00
Joe Farebrother
f57ba3e642 Add change note 2024-04-24 14:05:40 +01:00
Joe Farebrother
d4a072818f Add more tests 2024-04-24 14:05:40 +01:00
Joe Farebrother
eeef062f7c Implement sinks for wsgiref + allow lists in bulk header updates + local flow 2024-04-24 14:05:39 +01:00
Joe Farebrother
9d56f3eb68 Fix qldoc formatting 2024-04-24 14:05:39 +01:00
Joe Farebrother
cf8db4e425 Update instances of experimental concept to the main one, and anotate missing experimental test results. 2024-04-24 14:05:39 +01:00
Joe Farebrother
daa31b5bb7 Add documentation 2024-04-24 14:05:38 +01:00
Joe Farebrother
8636a50190 Fix qldoc + remove deprecation from experimental concepts (as they are still used in another experimental query) 2024-04-24 14:05:38 +01:00
Joe Farebrother
fa28d94363 Added a sanitizer for replacing newlines. 2024-04-24 14:05:38 +01:00
Joe Farebrother
dbbc944f32 Correct spelling 2024-04-24 14:05:38 +01:00
Joe Farebrother
a88ad62c00 Implemented sinks for bulk header updates, and added corresponding tests. 2024-04-24 14:05:38 +01:00
Joe Farebrother
3e9341ff8a Model class instantiation for werkzueg headers 2024-04-24 14:05:37 +01:00
Joe Farebrother
b9984beb16 Add test cases 2024-04-24 14:05:37 +01:00
Joe Farebrother
68d90918cf Add to header write concept a specification of whether the name or value arg allows newlines.
Ported sink defenitions from Flask and Werzeug from experimental to main.
Removed experimental sink definitions for Django, as neither name nor value are vulnerable.
2024-04-24 14:05:37 +01:00
Joe Farebrother
25ffcb2fde Split into customizations file 2024-04-24 14:05:37 +01:00
Joe Farebrother
6021d9238c Move headers injection query and concept from experimental to main 2024-04-24 14:05:37 +01:00
Anders Schack-Mulligen
830b83f653 Dataflow: Use doublyBoundedFastTC. 2024-04-23 13:07:20 +02:00
Joe Farebrother
f85ee38e04 Add instance taint steps for requests 2024-04-22 16:03:39 +01:00
Joe Farebrother
88e3227ed0 Add pyramid models 2024-04-22 13:27:18 +01: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
erik-krogh
6d3244d01c update expected outputs with an FP 2024-04-05 09:36:44 +02:00
erik-krogh
3ab73c8552 C++: Improve the cpp/path-injection qhelp 2024-04-05 09:36:39 +02: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
605 changed files with 16986 additions and 12244 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
)

View File

@@ -7,8 +7,6 @@ on:
- .github/workflows/go-tests-other-os.yml
- .github/actions/**
- codeql-workspace.yml
env:
GO_VERSION: '~1.22.0'
permissions:
contents: read
@@ -18,72 +16,17 @@ jobs:
name: Test MacOS
runs-on: macos-latest
steps:
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
id: go
- name: Check out code
uses: actions/checkout@v4
- name: Set up CodeQL CLI
uses: ./.github/actions/fetch-codeql
- name: Enable problem matchers in repository
shell: bash
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
- name: Build
run: |
cd go
make
- name: Cache compilation cache
id: query-cache
uses: ./.github/actions/cache-query-compilation
with:
key: go-qltest
- name: Test
run: |
cd go
make test cache="${{ steps.query-cache.outputs.cache-dir }}"
- name: Run tests
uses: ./go/actions/test
test-win:
if: github.repository_owner == 'github'
name: Test Windows
runs-on: windows-latest-xl
steps:
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
id: go
- name: Check out code
uses: actions/checkout@v4
- name: Set up CodeQL CLI
uses: ./.github/actions/fetch-codeql
- name: Enable problem matchers in repository
shell: bash
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
- name: Build
run: |
cd go
make
- name: Cache compilation cache
id: query-cache
uses: ./.github/actions/cache-query-compilation
with:
key: go-qltest
- name: Test
run: |
cd go
make test cache="${{ steps.query-cache.outputs.cache-dir }}"
- name: Run tests
uses: ./go/actions/test

View File

@@ -16,9 +16,6 @@ on:
- .github/actions/**
- codeql-workspace.yml
env:
GO_VERSION: '~1.22.0'
permissions:
contents: read
@@ -28,51 +25,9 @@ jobs:
name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl
steps:
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
id: go
- name: Check out code
uses: actions/checkout@v4
- name: Set up CodeQL CLI
uses: ./.github/actions/fetch-codeql
- name: Enable problem matchers in repository
shell: bash
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
- name: Build
run: |
cd go
make
- name: Check that all Go code is autoformatted
run: |
cd go
make check-formatting
- name: Compile qhelp files to markdown
run: |
cd go
env QHELP_OUT_DIR=qhelp-out make qhelp-to-markdown
- name: Upload qhelp markdown
uses: actions/upload-artifact@v3
- name: Run tests
uses: ./go/actions/test
with:
name: qhelp-markdown
path: go/qhelp-out/**/*.md
- name: Cache compilation cache
id: query-cache
uses: ./.github/actions/cache-query-compilation
with:
key: go-qltest
- name: Test
run: |
cd go
make test cache="${{ steps.query-cache.outputs.cache-dir }}"
run-code-checks: true

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,9 +26,17 @@ repos:
name: Format bazel files
files: \.(bazel|bzl)
language: system
entry: bazel run //:buildifier
entry: bazel run //misc/bazel:buildifier
pass_filenames: false
# DISABLED: can be enabled by copying this config and installing `pre-commit` with `--config` on the copy
# - id: go-gen
# name: Check checked in generated files in go
# files: ^go/.*
# language: system
# entry: bazel run //go:gen
# pass_filenames: false
- id: codeql-format
name: Fix QL file formatting
files: \.qll?$

View File

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

View File

@@ -4,6 +4,8 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/codeql-queries) on [codeql.github.com](https://codeql.github.com).
Note that the CodeQL for Visual Studio Code documentation has been migrated to https://docs.github.com/en/code-security/codeql-for-vs-code/, but you can still contribute to it via a different repository. For more information, see [Contributing to GitHub Docs documentation](https://docs.github.com/en/contributing)."
## Change notes
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
@@ -43,7 +45,7 @@ If you have an idea for a query that you would like to share with other CodeQL u
3. **Formatting**
- The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code).
- The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://docs.github.com/en/code-security/codeql-for-vs-code/).
If you prefer, you can either:
1. install the [pre-commit framework](https://pre-commit.com/) and install the configured hooks on this repo via `pre-commit install`, or

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

@@ -4,7 +4,7 @@ This open source repository contains the standard CodeQL libraries and queries t
## How do I learn CodeQL and run queries?
There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL using the [CodeQL extension for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) and the [CodeQL CLI](https://codeql.github.com/docs/codeql-cli/).
There is extensive documentation about the [CodeQL language](https://codeql.github.com/docs/), writing CodeQL using the [CodeQL extension for Visual Studio Code](https://docs.github.com/en/code-security/codeql-for-vs-code/) and using the [CodeQL CLI](https://docs.github.com/en/code-security/codeql-cli).
## Contributing

View File

@@ -1,3 +1,7 @@
## 0.13.1
No user-facing changes.
## 0.13.0
### Breaking Changes

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.13.0
version: 0.13.1
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

@@ -830,6 +830,12 @@ newtype TTranslatedElement =
not ignoreExpr(dc)
)
} or
// The set of destructors to invoke after a handler for a `try` statement. These
// need to be special cased because the destructors need to run following an
// `ExceptionEdge`, but not following a `GotoEdge` edge.
TTranslatedDestructorsAfterHandler(Handler handler) {
exists(handler.getAnImplicitDestructorCall())
} or
// A precise side effect of an argument to a `Call`
TTranslatedArgumentExprSideEffect(Call call, Expr expr, int n, SideEffectOpcode opcode) {
not ignoreExpr(expr) and

View File

@@ -777,6 +777,72 @@ abstract class TranslatedHandler extends TranslatedStmt {
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
}
/**
* The IR translation of the destructor calls of the parent `TranslatedCatchByTypeHandler`.
*
* This object does not itself generate the destructor calls. Instead, its
* children provide the actual calls.
*/
class TranslatedDestructorsAfterHandler extends TranslatedElement,
TTranslatedDestructorsAfterHandler
{
Handler handler;
TranslatedDestructorsAfterHandler() { this = TTranslatedDestructorsAfterHandler(handler) }
override string toString() { result = "Destructor calls after handler: " + handler }
private TranslatedCall getTranslatedImplicitDestructorCall(int id) {
result.getExpr() = handler.getImplicitDestructorCall(id)
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getChild(0).getFirstInstruction(kind)
}
override Handler getAst() { result = handler }
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
override TranslatedElement getChild(int id) {
result = this.getTranslatedImplicitDestructorCall(id)
}
override predicate handlesDestructorsExplicitly() { any() }
override Declaration getFunction() { result = handler.getEnclosingFunction() }
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
exists(int id | child = this.getChild(id) |
// Transition to the next child, if any.
result = this.getChild(id + 1).getFirstInstruction(kind)
or
// And otherwise go to the next handler, if any.
not exists(this.getChild(id + 1)) and
result =
getTranslatedStmt(handler)
.getParent()
.(TranslatedTryStmt)
.getNextHandler(getTranslatedStmt(handler), kind)
)
}
override TranslatedElement getLastChild() {
result =
this.getTranslatedImplicitDestructorCall(max(int id |
exists(handler.getImplicitDestructorCall(id))
))
}
override Instruction getALastInstructionInternal() {
result = this.getLastChild().getALastInstruction()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
}
/**
* The IR translation of a C++ `catch` block that catches an exception with a
* specific type (e.g. `catch (const std::exception&)`).
@@ -790,10 +856,14 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
resultType = getVoidType()
}
override predicate handlesDestructorsExplicitly() { any() }
override TranslatedElement getChildInternal(int id) {
result = super.getChildInternal(id)
or
id = 0 and result = this.getParameter()
or
id = 1 and result = this.getDestructors()
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -810,7 +880,9 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
result = this.getParameter().getFirstInstruction(kind)
or
kind instanceof ExceptionEdge and
result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
if exists(this.getDestructors())
then result = this.getDestructors().getFirstInstruction(any(GotoEdge edge))
else result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
)
}
@@ -822,6 +894,8 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
private TranslatedParameter getParameter() {
result = getTranslatedParameter(stmt.getParameter())
}
private TranslatedDestructorsAfterHandler getDestructors() { result.getAst() = stmt }
}
/**
@@ -842,9 +916,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
}
}
class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override IfStmt stmt;
abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
@@ -857,6 +929,8 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
override predicate handlesDestructorsExplicitly() { any() }
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
@@ -867,25 +941,21 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
id = 3 and result = this.getElse()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
abstract predicate hasInitialization();
private TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
abstract TranslatedStmt getInitialization();
private TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
abstract TranslatedCondition getCondition();
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
}
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
abstract TranslatedStmt getThen();
private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
abstract TranslatedStmt getElse();
private predicate hasElse() { exists(stmt.getElse()) }
abstract predicate hasElse();
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
@@ -898,7 +968,11 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
else (
if this.hasAnImplicitDestructorCall()
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -906,7 +980,24 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) 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)
)
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) {
@@ -914,76 +1005,44 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
}
}
class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
override ConstexprIfStmt stmt;
class TranslatedIfStmt extends TranslatedIfLikeStmt {
override IfStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstConditionInstruction(kind)
}
override predicate hasInitialization() { exists(stmt.getInitialization()) }
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
id = 1 and result = this.getCondition()
or
id = 2 and result = this.getThen()
or
id = 3 and result = this.getElse()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
private TranslatedStmt getInitialization() {
override TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
private TranslatedCondition getCondition() {
override TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
override TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
override TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
override predicate hasElse() { exists(stmt.getElse()) }
}
class TranslatedConstExprIfStmt extends TranslatedIfLikeStmt {
override ConstexprIfStmt stmt;
override predicate hasInitialization() { exists(stmt.getInitialization()) }
override TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
private predicate hasElse() { exists(stmt.getElse()) }
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getThen().getFirstInstruction(kind)
override TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
}
override TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) and
result = this.getParent().getChildSuccessor(this, kind)
}
override TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
override Instruction getALastInstructionInternal() {
result = this.getThen().getALastInstruction()
or
result = this.getElse().getALastInstruction()
}
override predicate hasElse() { exists(stmt.getElse()) }
}
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
@@ -1163,6 +1222,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 +1277,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 +1305,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 +1352,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 +1365,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 +1391,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

@@ -1,3 +1,9 @@
## 0.9.12
### New Queries
* 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.
## 0.9.11
### Minor Analysis Improvements

View File

@@ -14,13 +14,32 @@ the program, or security vulnerabilities, by allowing an attacker to overwrite a
</overview>
<recommendation>
<p>
Ensure that all execution paths deallocate the allocated memory at most once. If possible, reassign
the pointer to a null value after deallocating it. This will prevent double-free vulnerabilities since
most deallocation functions will perform a null-pointer check before attempting to deallocate the memory.
Ensure that all execution paths deallocate the allocated memory at most once. In complex cases it may
help to reassign a pointer to a null value after deallocating it. This will prevent double-free vulnerabilities
since most deallocation functions will perform a null-pointer check before attempting to deallocate memory.
</p>
</recommendation>
<example><sample src="DoubleFree.cpp" />
<example>
<p>
In the following example, <code>buff</code> is allocated and then freed twice:
</p>
<sample src="DoubleFreeBad.cpp" />
<p>
Reviewing the code above, the issue can be fixed by simply deleting the additional call to
<code>free(buff)</code>.
</p>
<sample src="DoubleFreeGood.cpp" />
<p>
In the next example, <code>task</code> may be deleted twice, if an exception occurs inside the <code>try</code>
block after the first <code>delete</code>:
</p>
<sample src="DoubleFreeBad2.cpp" />
<p>
The problem can be solved by assigning a null value to the pointer after the first <code>delete</code>, as
calling <code>delete</code> a second time on the null pointer is harmless.
</p>
<sample src="DoubleFreeGood2.cpp" />
</example>
<references>

View File

@@ -0,0 +1,16 @@
void g() {
MyTask *task = nullptr;
try
{
task = new MyTask;
...
delete task;
...
} catch (...) {
delete task; // BAD: potential double-free
}
}

View File

@@ -0,0 +1,7 @@
int* f() {
int *buff = malloc(SIZE*sizeof(int));
do_stuff(buff);
free(buff); // GOOD: buff is only freed once.
int *new_buffer = malloc(SIZE*sizeof(int));
return new_buffer;
}

View File

@@ -0,0 +1,17 @@
void g() {
MyTask *task = nullptr;
try
{
task = new MyTask;
...
delete task;
task = nullptr;
...
} catch (...) {
delete task; // GOOD: harmless if task is NULL
}
}

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

@@ -1,22 +0,0 @@
int main(int argc, char** argv) {
char *userAndFile = argv[2];
{
char fileBuffer[FILENAME_MAX] = "/home/";
char *fileName = fileBuffer;
size_t len = strlen(fileName);
strncat(fileName+len, userAndFile, FILENAME_MAX-len-1);
// BAD: a string from the user is used in a filename
fopen(fileName, "wb+");
}
{
char fileBuffer[FILENAME_MAX] = "/home/";
char *fileName = fileBuffer;
size_t len = strlen(fileName);
// GOOD: use a fixed file
char* fixed = "jim/file.txt";
strncat(fileName+len, fixed, FILENAME_MAX-len-1);
fopen(fileName, "wb+");
}
}

View File

@@ -3,36 +3,57 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>Accessing paths controlled by users can allow an attacker to access unexpected resources. This
<p>Accessing paths controlled by users can allow an attacker to access unexpected resources. This
can result in sensitive information being revealed or deleted, or an attacker being able to influence
behavior by modifying unexpected files.</p>
<p>Paths that are naively constructed from data controlled by a user may contain unexpected special characters,
such as "..". Such a path may potentially point to any directory on the filesystem.</p>
<p>Paths that are naively constructed from data controlled by a user may be absolute paths, or may contain
unexpected special characters such as "..". Such a path could point anywhere on the file system.</p>
</overview>
<recommendation>
<p>Validate user input before using it to construct a filepath. Ideally, follow these rules:</p>
<p>Validate user input before using it to construct a file path.</p>
<ul>
<li>Do not allow more than a single "." character.</li>
<li>Do not allow directory separators such as "/" or "\" (depending on the filesystem).</li>
<li>Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to
".../...//" the resulting string would still be "../".</li>
<li>Ideally use a whitelist of known good patterns.</li>
</ul>
<p>Common validation methods include checking that the normalized path is relative and does not contain
any ".." components, or checking that the path is contained within a safe folder. The method you should use depends
on how the path is used in the application, and whether the path should be a single path component.
</p>
<p>If the path should be a single path component (such as a file name), you can check for the existence
of any path separators ("/" or "\"), or ".." sequences in the input, and reject the input if any are found.
</p>
<p>
Note that removing "../" sequences is <i>not</i> sufficient, since the input could still contain a path separator
followed by "..". For example, the input ".../...//" would still result in the string "../" if only "../" sequences
are removed.
</p>
<p>Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that
the user input matches one of these patterns.</p>
</recommendation>
<example>
<p>In this example, a username and file are read from the arguments to main and then used to access a file in the
user's home directory. However, a malicious user could enter a filename which contains special
characters. For example, the string "../../etc/passwd" will result in the code reading the file located at
"/home/[user]/../../etc/passwd", which is the system's password file. This could potentially allow them to
access all the system's passwords.</p>
<p>In this example, a file name is read from a user and then used to access a file.
However, a malicious user could enter a file name anywhere on the file system,
such as "/etc/passwd" or "../../../etc/passwd".</p>
<sample src="TaintedPath.c" />
<sample src="examples/TaintedPath.c" />
<p>
If the input should only be a file name, you can check that it doesn't contain any path separators or ".." sequences.
</p>
<sample src="examples/TaintedPathNormalize.c" />
<p>
If the input should be within a specific directory, you can check that the resolved path
is still contained within that directory.
</p>
<sample src="examples/TaintedPathFolder.c" />
</example>
<references>
@@ -41,6 +62,7 @@ access all the system's passwords.</p>
OWASP:
<a href="https://owasp.org/www-community/attacks/Path_Traversal">Path Traversal</a>.
</li>
<li>Linux man pages: <a href="https://man7.org/linux/man-pages/man3/realpath.3.html">realpath(3)</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,10 @@
int main(int argc, char** argv) {
char *userAndFile = argv[2];
{
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/%s", userAndFile);
// BAD: a string from the user is used in a filename
fopen(fileBuffer, "wb+");
}
}

View File

@@ -0,0 +1,28 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char *userAndFile = argv[2];
const char *baseDir = "/home/user/public/";
char fullPath[PATH_MAX];
// Attempt to concatenate the base directory and the user-supplied path
snprintf(fullPath, sizeof(fullPath), "%s%s", baseDir, userAndFile);
// Resolve the absolute path, normalizing any ".." or "."
char *resolvedPath = realpath(fullPath, NULL);
if (resolvedPath == NULL) {
perror("Error resolving path");
return 1;
}
// Check if the resolved path starts with the base directory
if (strncmp(baseDir, resolvedPath, strlen(baseDir)) != 0) {
free(resolvedPath);
return 1;
}
// GOOD: Path is within the intended directory
FILE *file = fopen(resolvedPath, "wb+");
free(resolvedPath);
}

View File

@@ -0,0 +1,16 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char *fileName = argv[2];
// Check for invalid sequences in the user input
if (strstr(fileName , "..") || strchr(fileName , '/') || strchr(fileName , '\\')) {
printf("Invalid filename.\n");
return 1;
}
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/user/files/%s", fileName);
// GOOD: We know that the filename is safe and stays within the public folder
FILE *file = fopen(fileBuffer, "wb+");
}

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,5 @@
## 0.9.12
### New Queries
* Added a new query, `cpp/iterator-to-expired-container`, to detect the creation of iterators owned by a temporary objects that are about to be destroyed.

View File

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

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

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

@@ -2,6 +2,8 @@ edges
| test.c:8:27:8:30 | **argv | test.c:9:23:9:29 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:31:22:31:28 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:69:14:69:20 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:80:25:80:31 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:88:22:88:28 | *access to array | provenance | |
| test.c:9:23:9:29 | *access to array | test.c:17:11:17:18 | *fileName | provenance | TaintFunction |
| test.c:31:22:31:28 | *access to array | test.c:32:11:32:18 | *fileName | provenance | |
| test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | *fileName | provenance | |
@@ -11,6 +13,8 @@ edges
| test.c:54:21:54:26 | *call to getenv | test.c:55:11:55:16 | *buffer | provenance | TaintFunction |
| test.c:74:13:74:18 | read output argument | test.c:76:11:76:16 | *buffer | provenance | |
| test.c:75:13:75:18 | read output argument | test.c:76:11:76:16 | *buffer | provenance | |
| test.c:80:25:80:31 | *access to array | test.c:84:11:84:20 | *fileBuffer | provenance | TaintFunction |
| test.c:88:22:88:28 | *access to array | test.c:98:24:98:33 | *fileBuffer | provenance | TaintFunction |
nodes
| test.c:8:27:8:30 | **argv | semmle.label | **argv |
| test.c:9:23:9:29 | *access to array | semmle.label | *access to array |
@@ -30,6 +34,10 @@ nodes
| test.c:74:13:74:18 | read output argument | semmle.label | read output argument |
| test.c:75:13:75:18 | read output argument | semmle.label | read output argument |
| test.c:76:11:76:16 | *buffer | semmle.label | *buffer |
| test.c:80:25:80:31 | *access to array | semmle.label | *access to array |
| test.c:84:11:84:20 | *fileBuffer | semmle.label | *fileBuffer |
| test.c:88:22:88:28 | *access to array | semmle.label | *access to array |
| test.c:98:24:98:33 | *fileBuffer | semmle.label | *fileBuffer |
subpaths
#select
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | **argv | test.c:17:11:17:18 | *fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |
@@ -41,3 +49,5 @@ subpaths
| test.c:69:14:69:20 | access to array | test.c:8:27:8:30 | **argv | test.c:69:14:69:20 | *access to array | This argument to a file access function is derived from $@ and then passed to readFile(fileName), which calls fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |
| test.c:76:11:76:16 | buffer | test.c:74:13:74:18 | read output argument | test.c:76:11:76:16 | *buffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:74:13:74:18 | read output argument | user input (buffer read by read) |
| test.c:76:11:76:16 | buffer | test.c:75:13:75:18 | read output argument | test.c:76:11:76:16 | *buffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:75:13:75:18 | read output argument | user input (buffer read by read) |
| test.c:84:11:84:20 | fileBuffer | test.c:8:27:8:30 | **argv | test.c:84:11:84:20 | *fileBuffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |
| test.c:98:24:98:33 | fileBuffer | test.c:8:27:8:30 | **argv | test.c:98:24:98:33 | *fileBuffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |

View File

@@ -2,7 +2,7 @@
// Associated with CWE-022: Improper Limitation of a Pathname to a Restricted Directory. http://cwe.mitre.org/data/definitions/22.html
#include "stdlib.h"
#define PATH_MAX 4096
///// Test code /////
int main(int argc, char** argv) {
@@ -75,6 +75,55 @@ int main(int argc, char** argv) {
read(0, buffer, 1024);
fopen(buffer, "wb+"); // BAD [duplicated with both sources]
}
{
char *userAndFile = argv[2];
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/%s", userAndFile);
// BAD: a string from the user is used in a filename
fopen(fileBuffer, "wb+");
}
{
char *fileName = argv[2];
// Check for invalid sequences in the user input
if (strstr(fileName , "..") || strchr(fileName , '/') || strchr(fileName , '\\')) {
printf("Invalid filename.\n");
return 1;
}
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/user/files/%s", fileName);
// GOOD: We know that the filename is safe and stays within the public folder. But we currently get an FP here.
FILE *file = fopen(fileBuffer, "wb+");
}
{
char *userAndFile = argv[2];
const char *baseDir = "/home/user/public/";
char fullPath[PATH_MAX];
// Attempt to concatenate the base directory and the user-supplied path
snprintf(fullPath, sizeof(fullPath), "%s%s", baseDir, userAndFile);
// Resolve the absolute path, normalizing any ".." or "."
char *resolvedPath = realpath(fullPath, 0); // <- we're using `NULL` in the example, but 0 here to get it to compile. Same for next line.
if (resolvedPath == 0) {
perror("Error resolving path");
return 1;
}
// Check if the resolved path starts with the base directory
if (strncmp(baseDir, resolvedPath, strlen(baseDir)) != 0) {
free(resolvedPath);
return 1;
}
// GOOD: Path is within the intended directory
FILE *file = fopen(resolvedPath, "wb+");
free(resolvedPath);
}
}
void readFile(char *fileName) {

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

@@ -1,3 +1,3 @@
description: Remove 'kind' from 'attributes'.
compatability: full
attributes.rel: reorder attributes.rel (int id, int kind, int type_id, int target) id type_id target
attributes.rel: reorder attributes.rel (@attribute id, int kind, @type_or_ref type_id, @attributable target) id type_id target

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())

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