Compare commits

..

230 Commits

Author SHA1 Message Date
Nick Rolfe
740fd27707 Ruby: add dataflow for getters/setters defined using alias_attribute 2022-11-08 12:47:05 +00:00
Tony Torralba
d813590780 Merge pull request #11156 from atorralba/atorralba/swift/bitwise-operation
Swift: Add `BitwiseOperation.qll`
2022-11-08 12:15:00 +01:00
Tony Torralba
4411852e59 Add BitwiseOperation.qll 2022-11-08 11:33:10 +01:00
Jeroen Ketema
e00585ca24 Merge pull request #11154 from jketema/dataflow-test-fix
C++: Fix wrong return types and missing statement in dataflow test
2022-11-08 10:55:09 +01:00
AlexDenisov
d1848194eb Merge pull request #11152 from github/redsun82/swift-bitwise-test
Swift: add bitwise ops to `PrintAst` test
2022-11-08 10:25:48 +01:00
Tamás Vajk
38abd389eb Merge pull request #11045 from tamasvajk/kotlin-confusing-default
Kotlin: Excluded compiler generated methods from `java/confusing-method-signature`
2022-11-08 10:25:36 +01:00
Jeroen Ketema
0d4a2239fc C++: Fix wrong return types and missing statement in dataflow test 2022-11-08 09:55:10 +01:00
Paolo Tranquilli
072edad0fd Swift: accept new test changes 2022-11-08 09:30:25 +01:00
Erik Krogh Kristensen
c82410fd16 Merge pull request #10680 from erik-krogh/unsafeRbCmd
RB: add an unsafe-shell-command-construction query
2022-11-08 09:22:33 +01:00
Paolo Tranquilli
21adcca065 Swift: add bitwise ops to PrintAst test 2022-11-08 08:53:36 +01:00
Harry Maclean
8c8f1418d5 Merge pull request #11150 from hmac/try-fixup
Ruby: Cosmetic change
2022-11-08 12:19:47 +13:00
Harry Maclean
03aa8df8e2 Ruby: Cosmetic change 2022-11-08 10:24:21 +13:00
Harry Maclean
d392cdaab6 Merge pull request #11022 from hmac/try-code-injection
Ruby: try/try! as code execution
2022-11-08 09:42:52 +13:00
Tony Torralba
ef967b6a21 Merge pull request #10890 from atorralba/atorralba/android-startactivities-summaries
Java: Add flow summaries for startActivities
2022-11-07 18:06:30 +01:00
Alexander Eyers-Taylor
c6c4a7b14f Merge pull request #11068 from alexet/alexet/qlspec-instanceof
QL Spec: Add instanceof in classes
2022-11-07 16:15:09 +00:00
Erik Krogh Kristensen
3f871a08e2 apply suggestions from doc review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2022-11-07 16:29:10 +01:00
Tamás Vajk
ed305d2699 Merge pull request #11032 from tamasvajk/kotlin-unused-for-loop-var
Kotlin: exclude loop variables on ranges from 'unused locals' check
2022-11-07 15:44:10 +01:00
Karim Ali
5766ff21d0 Merge pull request #10993 from karimhamdanali/swift-pbe-constant-salts
Swift: detect the use of constant salts
2022-11-07 16:22:41 +02:00
Stephan Brandauer
577f1a588b Merge pull request #11143 from github/codeql-ci/atm/release-0.4.0
JS: Bump version numbers of ML-powered packs after 0.4.0 release
2022-11-07 15:03:24 +01:00
Erik Krogh Kristensen
d67235b3c1 Merge pull request #11071 from erik-krogh/fixCanon
ReDoS: fix canonicalization in NfaUtils
2022-11-07 14:10:50 +01:00
github-actions[bot]
69df9f9daa JS: Bump version of ML-powered library and query packs to 0.4.1 2022-11-07 13:06:46 +00:00
github-actions[bot]
82277d8f56 JS: Bump minor version of ML-powered library and query packs 2022-11-07 13:00:28 +00:00
github-actions[bot]
268a990aa6 JS: Bump version of ML-powered model pack to 0.3.1 2022-11-07 13:00:28 +00:00
github-actions[bot]
a1e0bf022e ATM: Update model pack dependency of ML-powered model building and query packs 2022-11-07 13:00:27 +00:00
github-actions[bot]
be808deb59 JS: Bump minor version of ML-powered model pack 2022-11-07 12:59:44 +00:00
Chris Smowton
eb365c1d24 Merge pull request #11079 from smowton/smowton/test/test-java-extractor-vs-captured-type-variables
Java: Add test for multiply-bounded wildcards
2022-11-07 12:31:19 +00:00
Tamás Vajk
830be92f1d Merge pull request #11089 from tamasvajk/kotlin-enum-ctor-call
Kotlin: Extract missing arguments of enum constructor calls
2022-11-07 12:55:27 +01:00
AlexDenisov
f8e80f96ff Merge pull request #11124 from github/redsun82/swift-await
Swift: extract `AwaitExpr`
2022-11-07 12:52:42 +01:00
Karim Ali
1756feae71 address docs review 2022-11-07 13:20:02 +02:00
Paolo Tranquilli
b30a6d36b5 Swift: extract AwaitExpr 2022-11-07 12:08:51 +01:00
Paolo Tranquilli
b94066acd8 Merge pull request #11094 from github/redsun82/swift-translators
Swift: refactor visitors to use translations
2022-11-07 12:01:44 +01:00
Geoffrey White
7b62bed9db Merge pull request #10947 from karimhamdanali/swift-pbe-iterations
Swift: detect hash functions with low # of iterations
2022-11-07 10:38:29 +00:00
Chris Smowton
e877967a62 Add test verifying no malformed wildcards result from captured type variables with a Collection<? extends ...> type 2022-11-07 10:29:04 +00:00
Chris Smowton
d999c1d3dd Java: Add test for multiply-bounded wildcards
This exercises several cases of variables bounded both by a wildcard and by a bound on the type parameter, checking that the extractor strips the wildcards and captures to decide on a concrete type for the parameters and return values.
2022-11-07 10:29:04 +00:00
Chris Smowton
1cd30847f6 Merge pull request #11121 from smowton/smowton/fix/java-wildcard-extraction
Kotlin: fix extraction of Java nested wildcards; wildcards in return types
2022-11-07 10:23:02 +00:00
Chris Smowton
68face8d46 Merge pull request #11130 from smowton/smowton/fix/kotlin-always-extract-file-labels
Kotlin: always populate the `files` table
2022-11-07 10:14:41 +00:00
Jeroen Ketema
d62e3f6bc2 Merge pull request #11137 from jketema/dataflow-test-fixes
C++: Small fixes for the dataflow tests
2022-11-07 11:07:09 +01:00
Anders Schack-Mulligen
99ca28ea9b Merge pull request #10886 from aschackmull/dataflow/joinorders
Dataflow: Fix a couple of join-orders.
2022-11-07 11:05:29 +01:00
Chris Smowton
587aa93f6d Merge pull request #11105 from smowton/smowton/fix/use-defaults-method-to-implement-jvmoverloads
Kotlin: use `$default` functions to implement `@JvmOverloads`
2022-11-07 09:54:16 +00:00
Tamas Vajk
4e8d8a4de1 Add compilerGeneratedReason for enum constructor call arguments 2022-11-07 10:07:05 +01:00
Tamas Vajk
7d927a7396 Adjust enum constructor argument extraction based on review 2022-11-07 10:07:05 +01:00
Tamas Vajk
fb5b344427 Fix failing build on early kotlin versions 2022-11-07 10:07:05 +01:00
Tamas Vajk
44e70afa85 Kotlin: Extract missing arguments of enum constructor calls 2022-11-07 10:07:04 +01:00
Jeroen Ketema
291027ad82 C++: Fix return type in dataflow test 2022-11-07 09:42:54 +01:00
Jeroen Ketema
3b1feeef6d C++: Remove unneeded isAdditionalFlowStep from dataflow test
Since the introduction of flow through global variables these additional
steps are no longer needed.
2022-11-07 09:40:57 +01:00
Dave Bartolomeo
b8e1aa67d8 Merge pull request #11134 from github/post-release-prep/codeql-cli-2.11.3
Post-release preparation for codeql-cli-2.11.3
2022-11-05 13:54:49 -04:00
github-actions[bot]
fca754bddd Post-release preparation for codeql-cli-2.11.3 2022-11-05 14:30:48 +00:00
Dave Bartolomeo
8344d5a376 Merge pull request #11133 from github/release-prep/2.11.3
Release preparation for version 2.11.3
2022-11-04 22:50:41 -04:00
Mathias Vorreiter Pedersen
60ac031db4 Merge pull request #11036 from geoffw0/simplify3 2022-11-05 00:31:05 +00:00
Dave Bartolomeo
013b7eff1c Apply suggestions from code review
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2022-11-04 18:46:32 -04:00
github-actions[bot]
508327235a Release preparation for version 2.11.3 2022-11-04 20:16:23 +00:00
Tiferet Gazit
5198ad7612 Merge pull request #11055 from github/tiferet/sink-classification-reasons
Sink endpoint characteristics
2022-11-04 11:24:08 -07:00
Henry Mercer
b32f4b844a Merge pull request #11118 from github/henrymercer/atm-check-queries-improvements
ATM: Miscellaneous improvements for the check queries workflow
2022-11-04 18:04:32 +00:00
tiferet
833041c62e Fix QLDoc style errors 2022-11-04 09:30:31 -07:00
tiferet
2aa4651534 Remove predicates not yet used from the current PR 2022-11-04 09:30:31 -07:00
tiferet
74c8bfff4f Minor changes from code review 2022-11-04 09:30:31 -07:00
tiferet
e60c016fc6 Format fixes 2022-11-04 09:30:31 -07:00
tiferet
cbf81b8839 Improve the import structure 2022-11-04 09:30:31 -07:00
tiferet
300456cd3e Enforce the abstraction over characteristics:
Make the implementations of specific `EndpointCharacteristic`s private.
2022-11-04 09:30:31 -07:00
tiferet
c0cc754fb5 Rename ClassificationReasons
Change the name to EndpointCharacteristics.
2022-11-04 09:30:30 -07:00
tiferet
a4939b91e7 Generalize the definition of a known sink:
If the list of reasons includes positive indicators with maximal confidence for this class, it's a known sink for the class.

This negates the need for each query config to define the isKnownSink predicate individually.
2022-11-04 09:30:29 -07:00
tiferet
08bbe596a2 Create the sink ClassificationReasons
Write the reasons that indicate that an endpoint is a sink for each sink type.

Also fix import error.
2022-11-04 09:30:29 -07:00
Dave Bartolomeo
649c3af98a Merge pull request #11127 from github/henrymercer/fix-atm-pr-checks
ATM: Fix CodeQL pack workspace references
2022-11-04 12:19:42 -04:00
Arthur Baars
58c0e65542 Merge pull request #11129 from aibaars/improve-weak-crypto
Ruby: Improve weak crypto query
2022-11-04 16:31:55 +01:00
alexet
c07db098a7 QLSpec: Adress comments from review 2022-11-04 15:27:21 +00:00
Chris Smowton
8fd4041511 Kotlin: always populate the files table
Previously individual top-level file declarations relied on their corresponding file-class to declare their `File` instance, but this can be scuppered by a Java extractor replacing that file-class and identifying a different file location.
2022-11-04 15:00:27 +00:00
Arthur Baars
98f4c29913 Ruby: weak crypto: do not report weak hash algorithms
Weak hash algorithms such as MD5 and SHA1 are often
used in non security sensitive contexts and reporting
all uses is far too noisy.
2022-11-04 15:58:50 +01:00
Erik Krogh Kristensen
418d632738 Merge pull request #11123 from erik-krogh/stableCI-followup-2
fix typo in compile-queries workflow
2022-11-04 15:48:27 +01:00
AlexDenisov
c7da814bca Merge pull request #11122 from github/alexdenisov/make-macos-sed-happy
Swift: make sed on macos happy
2022-11-04 15:45:06 +01:00
Paolo Tranquilli
0370d1a1ba Merge pull request #11008 from github/redsun82/swift-macos-integration-tests
Swift: rework workflows
2022-11-04 15:44:42 +01:00
Tom Hvitved
05bf86acb6 Merge pull request #11126 from hvitved/cpp/position-overrides
C++: Let `(Indirect|Direct)Position` be sub classes of `Position`
2022-11-04 15:35:27 +01:00
AlexDenisov
0260ecfbdb Merge branch 'main' into alexdenisov/make-macos-sed-happy 2022-11-04 15:17:08 +01:00
Henry Mercer
0b9588bf9e ATM: Add test pack to workspace 2022-11-04 14:07:14 +00:00
Henry Mercer
3e863a539a ATM: Fix CodeQL pack workspace references
This fixes the
[ATM PR checks](https://github.com/github/codeql/actions/runs/3392995797/jobs/5639827326)
breaking on main as a result of
https://github.com/github/codeql/pull/11004.
2022-11-04 14:03:34 +00:00
Tom Hvitved
95835b8297 C++: Let (Indirect|Direct)Position be sub classes of Position 2022-11-04 14:31:18 +01:00
erik-krogh
def9b5e2ce fix typo in compile-queries workflow 2022-11-04 13:58:29 +01:00
Erik Krogh Kristensen
265838aa2c Merge pull request #11117 from erik-krogh/stableCI-followup
fix merge-base compilation when running directly on main
2022-11-04 13:56:41 +01:00
AlexDenisov
476bbfbdb7 Update qltest.sh 2022-11-04 13:04:24 +01:00
Henry Mercer
cbbff0c401 ATM: Rename workflow
Rename to take into account us now checking the results of the query
suite too.
2022-11-04 11:51:35 +00:00
Henry Mercer
87f7b65052 ATM: Check the results of the queries too 2022-11-04 11:51:35 +00:00
Erik Krogh Kristensen
91b33f72b5 update name and comment to reflect that it also runs on rc branches 2022-11-04 12:50:18 +01:00
Anders Schack-Mulligen
a1dba82360 Dataflow: Sync. 2022-11-04 12:41:55 +01:00
Anders Schack-Mulligen
828d187198 Dataflow: Fix a couple of join-orders. 2022-11-04 12:41:55 +01:00
Tamás Vajk
545dd8b8d8 Merge pull request #11106 from tamasvajk/kotlin-binop-ext
Kotlin: Extract extension binary operators
2022-11-04 12:41:06 +01:00
Chris Smowton
ca04779dfc Kotlin: fix extraction of Java nested wildcards; wildcards in return types
This fixes two mistakes: return-type extraction not imposing a wildcard where a Java prototype explicitly uses one, and nested wildcard detection quietly failing due to not looking through a `JavaWildcardType` correctly.

I add a variant of the `kotlin_java_lowering_wildcards` test where Java prototypes are only seen from Kotlin, to be sure extraction is working as expected.
2022-11-04 11:39:26 +00:00
Henry Mercer
fe27e09a07 ATM: Add codeowners entry for new workflow 2022-11-04 10:57:00 +00:00
Henry Mercer
05dd161d76 ATM: Use database analyze to check results interpretation too 2022-11-04 10:54:08 +00:00
Henry Mercer
7976d746b6 ATM: Simplify DB path definition and improve quoting 2022-11-04 10:49:25 +00:00
Henry Mercer
35a4d31519 ATM: Fix naming of query pack 2022-11-04 10:46:06 +00:00
Henry Mercer
f558e858e7 ATM: Install codeql using new input to fetch-codeql Action 2022-11-04 10:44:14 +00:00
Paolo Tranquilli
2bec4479e7 Merge pull request #11029 from github/redsun82/swift-filtered-debugging
Swift: add possibility to run the extractor under an env-specified tool
2022-11-04 11:44:11 +01:00
erik-krogh
47289a4d33 fix merge-base compilation when running directly on main 2022-11-04 11:28:56 +01:00
Erik Krogh Kristensen
ec87a932b8 Merge pull request #11078 from erik-krogh/stableCI
add workflow that checks compilation of all queries with the latest stable release
2022-11-04 11:21:23 +01:00
Erik Krogh Kristensen
c82d8cbacc Merge pull request #11013 from erik-krogh/sndCmd
JS: second-order-command-injection
2022-11-04 10:58:50 +01:00
Paolo Tranquilli
daa4e99a2f Swift: fix executable permissions
These were broken by a merge done in the github UI.
2022-11-04 10:47:47 +01:00
Paolo Tranquilli
fdde84ac35 Merge branch 'main' into redsun82/swift-filtered-debugging 2022-11-04 10:42:48 +01:00
Paolo Tranquilli
858ae3dab4 Merge pull request #11116 from github/redsun82/swift-expect-failure-in-qltest
Swift: allow expecting failure in qltest.sh
2022-11-04 10:40:41 +01:00
Tom Hvitved
2f8dcdd602 Merge pull request #10933 from hvitved/csharp/fix-flow-into-phis
C#: Fix flow steps into phi/uncertain def nodes
2022-11-04 10:28:09 +01:00
Tom Hvitved
587e6739d9 Merge pull request #11060 from hvitved/dataflow/path-node-reach-charpred
Data flow: Restrict public `PathNode`s to those that may reach a sink
2022-11-04 10:17:09 +01:00
Paolo Tranquilli
231f2238c1 Swift: fix wrong test names 2022-11-04 10:06:57 +01:00
Paolo Tranquilli
4cfe11c319 Swift: allow expecting failure in qltest.sh 2022-11-04 10:03:00 +01:00
Anders Schack-Mulligen
331b8c0144 Merge pull request #10904 from aschackmull/java/joinorders
Java: Fix some join-orders.
2022-11-04 09:24:31 +01:00
Paolo Tranquilli
3a8efb3db1 Swift: make visit arguments pointers again 2022-11-04 06:06:05 +01:00
Geoffrey White
d69d289020 Swift: remove getArgumentByParamName (for now). 2022-11-03 18:56:13 +00:00
Paolo Tranquilli
e0eb820ef9 Swift: fix extraction of BuiltinIntegerLiteralType 2022-11-03 18:16:54 +01:00
Paolo Tranquilli
a1d798b817 Swift: make visit arguments references instead of pointers 2022-11-03 18:16:53 +01:00
Paolo Tranquilli
cc9dafffde Swift: encapsulate swift::ASTVisitor functionality 2022-11-03 18:16:53 +01:00
Paolo Tranquilli
7c9fffc201 Swift: rename all visitors to translators 2022-11-03 18:16:53 +01:00
Paolo Tranquilli
75f30a8f9c Swift: refactor ExprVisitor to use translations 2022-11-03 18:16:53 +01:00
Paolo Tranquilli
a6b1806e66 Swift: refactor TypeVisitor to use translations 2022-11-03 18:16:53 +01:00
Paolo Tranquilli
c8cb30f76e Swift: refactor StmtVisitor to use translations
Also make `visit` in `SwiftDispatcher` work on `const` pointers.

Also, fixed a bug where the guard of a `CaseLabelItem` was not being
extracted, hence the test updates.
2022-11-03 18:16:53 +01:00
Paolo Tranquilli
faf10294ed Swift: refactor PatternVisitor to use translations 2022-11-03 18:16:53 +01:00
Paolo Tranquilli
4702271102 Swift: add cfg.swift to AST tests 2022-11-03 18:16:53 +01:00
Nora Dimitrijević
924f999aa8 Merge pull request #11104 from github/swift/webviewjoinorder 2022-11-03 16:44:17 +01:00
Erik Krogh Kristensen
1f51bd4594 add dash in description
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2022-11-03 16:24:59 +01:00
Tamas Vajk
16cb4c5aaa Kotlin: Extract extension binary operators 2022-11-03 16:11:23 +01:00
Tamas Vajk
70561cabaf Kotlin: Add test cases for extension binary operators 2022-11-03 16:10:32 +01:00
Tom Hvitved
1711efcc47 C#: Update expected test output 2022-11-03 15:52:30 +01:00
Tom Hvitved
a533c95640 C++: Update expected test output 2022-11-03 15:52:30 +01:00
Tom Hvitved
d3488da0c2 Data flow: Sync files 2022-11-03 15:52:30 +01:00
Tom Hvitved
cc87d2e38b Data flow: Restrict public PathNodes to those that may reach a sink 2022-11-03 15:52:30 +01:00
Chris Smowton
1ea87020c4 Kotlin: use $default functions to implement @JvmOverloads
This avoids extracting the default value expression in more than one place, which causes inconsistencies for e.g. anonymous classes, which expect to have a single `new` expression associated.
2022-11-03 14:48:36 +00:00
Nora Dimitrijević
0e67100cad Swift: fix bad join order in WebView/JsExportedSource
The `getName = getName` join was happening too early,
before the methods themselves have been enumerated.
2022-11-03 15:30:04 +01:00
Henry Mercer
12ab95668c Merge pull request #11098 from github/henrymercer/summary-metrics-consistent-naming
Summary metrics: Improve consistency of naming
2022-11-03 14:05:23 +00:00
Henry Mercer
8060b30cce Merge pull request #11099 from github/henrymercer/atm-labeler
Add ATM to labeler
2022-11-03 13:49:35 +00:00
Erik Krogh Kristensen
5918e0184c quote $CHANNEL
Co-authored-by: Arthur Baars <aibaars@github.com>
2022-11-03 14:17:44 +01:00
Mathias Vorreiter Pedersen
1ca7c5b97d Merge pull request #11091 from JarLob/assign
Fix AV Rule 76
2022-11-03 13:06:10 +00:00
erik-krogh
96ec54e5be fix minor issues in qhelp 2022-11-03 14:01:58 +01:00
erik-krogh
b5666888b1 rewrite @description of second-order-command-injection 2022-11-03 14:00:29 +01:00
erik-krogh
83a8b1afb8 use fetch-codeql action 2022-11-03 13:49:15 +01:00
Henry Mercer
7ce4629b12 Add ATM to labeler 2022-11-03 11:55:19 +00:00
Henry Mercer
dd264c6dfb Consistently mention language in metric names
This improves consistency between the lines of code queries and the
number of successfully extracted files queries.
2022-11-03 11:44:10 +00:00
Mathias Vorreiter Pedersen
ad0b36a0c9 C++: Add change note. 2022-11-03 11:41:38 +00:00
Henry Mercer
c60d071239 Lowercase "lines" 2022-11-03 11:40:22 +00:00
Tony Torralba
83caf01778 Merge pull request #11096 from atorralba/atorralba/swift/unit
Swift: Move the Unit class to its own file
2022-11-03 12:00:57 +01:00
erik-krogh
3159b3d9a1 swift: fix unused variable 2022-11-03 11:20:15 +01:00
erik-krogh
f9195d194b go: make sure the source/sink have the same type as the edges relation 2022-11-03 11:20:15 +01:00
erik-krogh
c9fcef2608 go: add a precision tag to go/examples/deferinloop 2022-11-03 11:20:15 +01:00
erik-krogh
1ec204987d go: remove precision from metric queries 2022-11-03 11:20:15 +01:00
erik-krogh
fc811bd33d add workflow that checks compilation of all queries with the latest stable release 2022-11-03 11:20:12 +01:00
Tony Torralba
978ed03e9c Move the Unit class to its own file 2022-11-03 11:19:41 +01:00
Chris Smowton
44b0f1921f Merge pull request #11090 from smowton/smowton/fix/value-parameter-label-external-class
Kotlin: drop same-file requirement for overridden parameter labels
2022-11-03 10:17:33 +00:00
Asger F
8502939b65 Merge pull request #11081 from asgerf/ql/dependency-paths
QL4QL: Add DependencyPath.ql query
2022-11-03 10:17:45 +01:00
Mathias Vorreiter Pedersen
01f3150a70 Merge pull request #11092 from hvitved/swift/avoid-deprecated-ssa-predicates
Swift: Avoid calls to deprecated SSA predicates
2022-11-03 09:03:47 +00:00
Asger F
fbcdb53d72 QL: Add option to follow 'cached' dependencies 2022-11-03 09:43:56 +01:00
erik-krogh
f3741ff1e4 changes based on review 2022-11-03 09:41:05 +01:00
Paolo Tranquilli
7e0a7d8b71 Swift: fix third-party action commit 2022-11-03 09:20:58 +01:00
Paolo Tranquilli
73131cef9e Merge branch 'main' into redsun82/swift-macos-integration-tests 2022-11-03 09:19:07 +01:00
Tom Hvitved
4e3fcc3235 Swift: Avoid calls to deprecated SSA predicates 2022-11-03 09:03:20 +01:00
Dave Bartolomeo
499f20f6e8 Merge pull request #11004 from dbartol/dbartol/use-workspace-versions 2022-11-02 20:02:48 -04:00
JarLob
3317223e19 Fix AV Rule 76 2022-11-02 22:50:25 +01:00
Tom Hvitved
46631d6eaf Merge pull request #10931 from hvitved/ruby/fix-flow-into-phis
Ruby: Fix flow steps into phi nodes
2022-11-02 21:07:06 +01:00
Chris Smowton
8e240a2e84 Kotlin: drop same-file requirement for overridden parameter labels 2022-11-02 19:28:53 +00:00
Dave Bartolomeo
15be488c53 Fix typo 2022-11-02 12:40:55 -04:00
Dave Bartolomeo
a475e5758d Merge remote-tracking branch 'upstream/main' into dbartol/use-workspace-versions 2022-11-02 12:38:03 -04:00
Dave Bartolomeo
7cad4b7918 Revert changes to ATM, which isn't in the workspace 2022-11-02 12:37:30 -04:00
Tamas Vajk
e48dfcc5b1 Kotlin: exclude loop variables on ranges from 'unused locals' check 2022-11-02 17:34:59 +01:00
Asger F
bac573bbed QL4QL: Add DependencyPath.ql query 2022-11-02 15:46:12 +01:00
Paolo Tranquilli
2c517a3237 Swift: fix codegen test invocation 2022-11-02 14:48:20 +01:00
Paolo Tranquilli
99764450b3 Swift: remove redundant test run 2022-11-02 14:44:33 +01:00
Paolo Tranquilli
bc65d358f2 Swift: fix wrongly exchanged action bodies 2022-11-02 14:43:57 +01:00
Paolo Tranquilli
6ce6d9dc37 Swift: fix quick tests action, again 2022-11-02 14:42:14 +01:00
Paolo Tranquilli
08909e5c69 Swift: fix quick tests action 2022-11-02 14:38:07 +01:00
Paolo Tranquilli
17012c1a45 Swift: fix workflow job dependencies 2022-11-02 14:35:23 +01:00
Paolo Tranquilli
e6d4685109 Swift: split quick tests in separate action
Also, make the quick test list explicit in the action code, so we can
catch an inadvertant test deletion.
2022-11-02 14:32:45 +01:00
Paolo Tranquilli
3acd4486a3 Swift: add tests for RUN_UNDER support
While I would have preferred to add a proper unit test, this required
more infrastructure for mocking system calls. Instead I made `qltest.sh`
accept a `//codeql-extractor-env` header and used that to write a QL
test exercising the `RUN_UNDER` functionality.
2022-11-02 12:09:13 +01:00
Tom Hvitved
fa762d9952 C#: Fix flow steps into phi nodes
- Add missing flow from post-update nodes into phi nodes.
- Prevent flow from reads into phi nodes when use-use flow is prohibited.
2022-11-02 10:21:50 +01:00
Tom Hvitved
5b5dd07d60 C#: Add data flow test that illustrates issue with flow into phi nodes 2022-11-02 10:20:56 +01:00
Tamas Vajk
a7cc8fced5 Adjust code based on review 2022-11-02 09:46:53 +01:00
Tamas Vajk
ec5ac17f87 Kotlin: Excluded compiler generated methods from java/confusing-method-signature 2022-11-02 09:40:31 +01:00
Tamas Vajk
556c199a89 Kotlin: Add test case for confusingly overloaded $default method 2022-11-02 09:40:31 +01:00
Paolo Tranquilli
82998ce3a3 Merge branch 'main' into redsun82/swift-filtered-debugging 2022-11-02 06:39:16 +01:00
Paolo Tranquilli
57a616262f Swift: fix run cwd 2022-11-02 06:27:09 +01:00
Paolo Tranquilli
0d9ecfc4de Swift: move small bazel tests to build action 2022-11-02 06:23:44 +01:00
Paolo Tranquilli
6e370beb92 Swift: turn on macOS QL tests with slicing 2022-11-02 06:07:55 +01:00
Geoffrey White
85e99feb49 Swift: Have swift/unsafe-webview-fetch use indices instead of parameter names. 2022-11-01 22:58:48 +00:00
Geoffrey White
d87117f623 Swift: Have swift/string-length-conflation use indices instead of parameter names. 2022-11-01 22:51:10 +00:00
erik-krogh
c15f63ce62 sync files 2022-11-01 21:35:27 +01:00
erik-krogh
15416a9c86 fix getCanonicalCharClass in NfaUtils 2022-11-01 21:35:07 +01:00
erik-krogh
78e35e2f29 add failing test 2022-11-01 21:33:19 +01:00
alexet
04a47093ee QL Spec: Add instanceof in classes 2022-11-01 18:31:43 +00:00
Dave Bartolomeo
9d5e5e3ee7 ${workspace} all the things 2022-11-01 13:29:05 -04:00
Dave Bartolomeo
49c4c554c4 Merge from main 2022-11-01 13:22:40 -04:00
Tom Hvitved
ee9163aa40 Ruby: Fix flow steps into phi nodes
- Add missing flow from post-update nodes into phi nodes.
- Prevent flow from reads into phi nodes when use-use flow is prohibited.
2022-11-01 16:33:06 +01:00
Tom Hvitved
a191edfbd5 Ruby: Add data flow tests that illustrate problems with flow into SSA phi nodes 2022-11-01 16:32:46 +01:00
erik-krogh
6f3ca40fed expand the explanation to include with arguments make the commands vulnerable 2022-11-01 14:24:23 +01:00
Erik Krogh Kristensen
8fd6424db9 fix the qhelp
Co-authored-by: Asger F <asgerf@github.com>
2022-11-01 14:05:25 +01:00
erik-krogh
5e5160d4fc add which commands are flagged in the change-note 2022-10-31 21:42:59 +01:00
Paolo Tranquilli
59284739dd Swift: reenable ql tests on macos 2022-10-31 17:07:56 +01:00
Paolo Tranquilli
80ea2b8c5e Swift: use macos-12-xl runners 2022-10-31 16:59:11 +01:00
Paolo Tranquilli
003866621f Swift: rework workflows
* A unique workflow file has been created merging all `swift-*.yml`
  workflows
* Change filtering at job level was added using [dorny/paths-filter][1]
* only one build of the extractor is made, and then shared via cache
  (not as an artifact because of [this longstading issue][2])
* integration tests are now run on on macOS
* qltests are not run any more on macOS to cut on feedback time
* autobuilder tests were moved to the macOS build step to avoid loading
  bazel twice

[1]: https://github.com/dorny/paths-filter#examples
[2]: https://github.com/actions/upload-artifact/issues/38
2022-10-31 16:59:11 +01:00
Karim Ali
3911f3b202 update query description following docs review 2022-10-31 13:54:35 +02:00
Karim Ali
76a330d4b9 update code example to be OWASP compliant 2022-10-31 13:52:49 +02:00
Karim Ali
723ca8ed88 update documentation following docs review 2022-10-31 13:50:30 +02:00
Paolo Tranquilli
2b395985e6 Swift: remove unneeded trailing / in README.md 2022-10-31 09:55:03 +01:00
Paolo Tranquilli
e62acb1e8c Swift: revert wrong paragraph edit in README.md 2022-10-31 09:54:15 +01:00
Paolo Tranquilli
7237362feb Swift: add debug path mapping to README.md
This allows breakpoints to work more reliably, including on a bazel
project in CLion.
2022-10-31 09:51:41 +01:00
Paolo Tranquilli
46c7ee0e4f Swift: refactor RUN_UNDER code 2022-10-31 09:51:20 +01:00
Paolo Tranquilli
80debe19e0 Swift: fix RUN_UNDER_FILTER check 2022-10-31 09:50:45 +01:00
Harry Maclean
0dd63c007e Ruby: Add change note 2022-10-31 11:53:22 +13:00
Harry Maclean
fd61a5253d Ruby: Recognise try/try! as code executions 2022-10-31 11:53:22 +13:00
erik-krogh
fc2112831c add second-order-command-injection query 2022-10-30 21:20:47 +01:00
Geoffrey White
840b74dbb5 Swift: Add and use ApplyExpr.getArgumentByParamName. 2022-10-28 17:55:11 +01:00
Paolo Tranquilli
3dcdc739de Swift: add possibility to run the extractor under an env-specified tool
if `CODEQL_EXTRACTOR_SWIFT_RUN_UNDER` env variable is set, and either
* `CODEQL_EXTRACTOR_SWIFT_RUN_UNDER_FILTER` is not set, or
* it is set to a regexp matching any substring of the extractor call
then the extractor process is substituted with the command (and possibly
options) stated in `CODEQL_EXTRACTOR_SWIFT_RUN_UNDER`, followed by the
system arguments of the extractor itself (which should include the
extractor program itself at the start).

Before calling `exec`, `CODEQL_EXTRACTOR_SWIFT_RUN_UNDER` is unset to
avoid unpleasant loops.

An example usage is to run the extractor under `gdbserver :1234` when
the arguments match a given source file.
2022-10-28 14:12:27 +02:00
erik-krogh
0a7e797090 update expected outputs after reordering tests 2022-10-28 10:16:21 +02:00
erik-krogh
946720f414 reorder the CWE-078 tests into subdirectories 2022-10-28 10:16:21 +02:00
Dave Bartolomeo
23b572e9b7 Use ${workspace} for intra-workspace dependencies
Now that the released CLI supports replacement variables in dependency version ranges, we can now mark our published library packs as depending on whatever version of their dependency is in our workspace, without having to manually bump the dependency version every release.

Note that when the packs are published, the dependencies in the published pack file are rewritten to have the correct specific version.
2022-10-26 16:40:01 -04:00
Karim Ali
420c35d4a2 add a query that detects the use of constant salts 2022-10-26 15:32:59 +02:00
Karim Ali
18dd0f650c update iterations threshold to most recent OWASP recommendation
which is at least 120,000 iterations for secure password hashing
2022-10-25 14:01:40 +02:00
Karim Ali
408c7bebe5 fix .expected file 2022-10-25 13:24:37 +02:00
Karim Ali
e8f55b9f0d update output message 2022-10-25 13:24:37 +02:00
Karim Ali
c0ac29db16 clarify qhelp + add references to it 2022-10-25 13:24:37 +02:00
Karim Ali
4b7cb706f6 fix error in checking # of iterations
plus also simplify the pattern matching of the sink classes
2022-10-25 13:24:37 +02:00
Karim Ali
0d2e7d43b9 add expected output 2022-10-25 13:24:37 +02:00
Karim Ali
5179a99abb fix test cases to use the correct class name 2022-10-25 13:24:37 +02:00
Karim Ali
c4b2519e6c initial draft of the Swift query for CWE-916 2022-10-25 13:24:37 +02:00
Anders Schack-Mulligen
9ebcaf80e7 Java: Fix some join-orders. 2022-10-20 14:23:36 +02:00
erik-krogh
7797211118 Merge branch 'main' into unsafeRbCmd 2022-10-20 10:34:17 +02:00
Tony Torralba
0678b06a9b Apply review suggestions 2022-10-19 16:58:43 +02:00
Tony Torralba
25241276b0 Add change note 2022-10-19 16:29:36 +02:00
Tony Torralba
429bd5fbd8 Add flow summaries for startActivities
Uses SyntheticCallables and SyntheticGlobals to pair each startActivities call to getIntent calls in the components targeted by the intent(s).
2022-10-19 16:25:04 +02:00
erik-krogh
0220f0aa5c use type-tracking instead 2022-10-11 13:37:01 +02:00
erik-krogh
b64a1b7c42 add a missing qldoc 2022-10-11 13:26:04 +02:00
erik-krogh
cadb948d57 add change-note 2022-10-11 13:26:03 +02:00
erik-krogh
d427e55507 add qhelp 2022-10-11 13:26:03 +02:00
erik-krogh
557dd10896 add a rb/unsafe-shell-command-construction query 2022-10-11 13:26:01 +02:00
erik-krogh
0d5da42ddd add a getName() utility to DataFlow::ParameterNode 2022-10-11 13:05:22 +02:00
erik-krogh
75422dfa72 add library for reasoning about gems and .gemspec files 2022-10-11 13:05:19 +02:00
erik-krogh
99b90789e5 add .shellescape as a sanitizer for rb/command-injection 2022-10-11 13:05:19 +02:00
erik-krogh
b16b3c0394 move cwe-078 tests into subfolders 2022-10-11 13:05:19 +02:00
459 changed files with 14740 additions and 7910 deletions

View File

@@ -1,14 +1,22 @@
name: Fetch CodeQL
description: Fetches the latest version of CodeQL
inputs:
channel:
description: 'The CodeQL channel to use'
required: false
default: 'nightly'
runs:
using: composite
steps:
- name: Fetch CodeQL
shell: bash
run: |
gh extension install github/gh-codeql
gh codeql set-channel nightly
gh codeql version
gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_PATH}"
env:
GITHUB_TOKEN: ${{ github.token }}
CHANNEL: ${{ inputs.channel }}
run: |
gh extension install github/gh-codeql
gh codeql set-channel "$CHANNEL"
gh codeql version
gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_PATH}"

3
.github/labeler.yml vendored
View File

@@ -51,3 +51,6 @@ documentation:
- "java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
- "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll"
- "java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll"
"ATM":
- javascript/ql/experimental/adaptivethreatmodeling/**/*

View File

@@ -1,56 +0,0 @@
name: ATM Check Queries Run
env:
DB_PATH: test_db
ATM_MODEL_PACK: javascript/ql/experimental/adaptivethreatmodeling/src
QUERY_SUITE: codeql-suites/javascript-atm-code-scanning.qls
on:
pull_request:
paths:
- ".github/workflows/atm-check-queries-run.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/**"
workflow_dispatch:
jobs:
run-atm-queries:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install CodeQL CLI
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh extensions install github/gh-codeql
gh codeql download
- name: Install ATM model pack
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -exu
# Install ATM model pack
gh codeql pack install ${ATM_MODEL_PACK}
# Retrieve model checksum
model_checksum=$(gh codeql resolve extensions ${ATM_MODEL_PACK}/${QUERY_SUITE} | jq -r '.models[0].checksum')
# Trust the model so that we can use it in the ATM boosted queries
mkdir -p "$HOME/.config/codeql"
echo "--insecurely-execute-ml-model-checksums ${model_checksum}" >> "$HOME/.config/codeql/config"
- name: Create test DB
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh codeql database create ${RUNNER_TEMP}/${DB_PATH} --source-root config/atm/ --language javascript
- name: Run ATM query suite
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh codeql database run-queries -vv -- ${RUNNER_TEMP}/${DB_PATH} ${ATM_MODEL_PACK}/${QUERY_SUITE}

View File

@@ -0,0 +1,93 @@
name: "ATM - Check query suite"
env:
QUERY_PACK: javascript/ql/experimental/adaptivethreatmodeling/src
QUERY_SUITE: codeql-suites/javascript-atm-code-scanning.qls
on:
pull_request:
paths:
- ".github/workflows/atm-check-query-suite.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/**"
workflow_dispatch:
jobs:
atm-check-query-suite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup CodeQL
uses: ./.github/actions/fetch-codeql
with:
channel: release
- name: Install ATM model
run: |
set -exu
# Install dependencies of ATM query pack, i.e. the ATM model
codeql pack install "${QUERY_PACK}"
# Retrieve model checksum
model_checksum=$(codeql resolve extensions "${QUERY_PACK}/${QUERY_SUITE}" | jq -r '.models[0].checksum')
# Trust the model so that we can use it in the ATM boosted queries
mkdir -p "$HOME/.config/codeql"
echo "--insecurely-execute-ml-model-checksums ${model_checksum}" >> "$HOME/.config/codeql/config"
- name: Create test DB
run: |
DB_PATH="${RUNNER_TEMP}/db"
echo "DB_PATH=${DB_PATH}" >> "${GITHUB_ENV}"
codeql database create "${DB_PATH}" --source-root config/atm --language javascript
- name: Run ATM query suite
run: |
SARIF_PATH="${RUNNER_TEMP}/sarif.json"
echo "SARIF_PATH=${SARIF_PATH}" >> "${GITHUB_ENV}"
codeql database analyze \
--format sarif-latest \
--output "${SARIF_PATH}" \
--sarif-group-rules-by-pack \
-vv \
-- \
"${DB_PATH}" \
"${QUERY_PACK}/${QUERY_SUITE}"
- name: Upload SARIF
uses: actions/upload-artifact@v3
with:
name: javascript-ml-powered-queries.sarif
path: "${{ env.SARIF_PATH }}"
retention-days: 5
- name: Check results
run: |
# We should run at least the ML-powered queries in `expected_rules`.
expected_rules="js/ml-powered/nosql-injection js/ml-powered/path-injection js/ml-powered/sql-injection js/ml-powered/xss"
for rule in ${expected_rules}; do
found_rule=$(jq --arg rule "${rule}" '[.runs[0].tool.extensions[].rules | select(. != null) |
flatten | .[].id] | any(. == $rule)' "${SARIF_PATH}")
if [[ "${found_rule}" != "true" ]]; then
echo "Expected SARIF output to contain rule '${rule}', but found no such rule."
exit 1
else
echo "Found rule '${rule}'."
fi
done
# We should have at least one alert from an ML-powered query.
num_alerts=$(jq '[.runs[0].results[] |
select(.properties.score != null and (.rule.id | startswith("js/ml-powered/")))] | length' \
"${SARIF_PATH}")
if [[ "${num_alerts}" -eq 0 ]]; then
echo "Expected to find at least one alert from an ML-powered query but found ${num_alerts}."
exit 1
else
echo "Found ${num_alerts} alerts from ML-powered queries.";
fi

57
.github/workflows/compile-queries.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: "Compile all queries using the latest stable CodeQL CLI"
on:
push:
branches: [main] # makes sure the cache gets populated
pull_request:
branches:
- main
- "rc/*"
jobs:
compile-queries:
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
# calculate the merge-base with main, in a way that works both on PRs and pushes to main.
- name: Calculate merge-base
if: ${{ github.event_name == 'pull_request' }}
env:
BASE_BRANCH: ${{ github.base_ref }}
run: |
MERGE_BASE=$(git merge-base --fork-point origin/$BASE_BRANCH)
echo "merge-base=$MERGE_BASE" >> $GITHUB_ENV
- name: Calculate merge-base - branch
if: ${{ github.event_name != 'pull_request' }}
# using github.sha instead, since we're directly on a branch, and not in a PR
run: |
MERGE_BASE=${{ github.sha }}
echo "merge-base=$MERGE_BASE" >> $GITHUB_ENV
- name: Cache CodeQL query compilation
uses: actions/cache@v3
with:
path: '*/ql/src/.cache'
# current GH HEAD first, merge-base second, generic third
key: codeql-stable-compile-${{ github.sha }}
restore-keys: |
codeql-stable-compile-${{ env.merge-base }}
codeql-stable-compile-
- name: Setup CodeQL
uses: ./.github/actions/fetch-codeql
with:
channel: 'release'
- name: check formatting
run: codeql query format */ql/{src,lib,test}/**/*.{qll,ql} --check-only
- name: compile queries - check-only
# run with --check-only if running in a PR (github.sha != main)
if : ${{ github.event_name == 'pull_request' }}
shell: bash
run: codeql query compile -j0 */ql/src --keep-going --warnings=error --check-only
- name: compile queries - full
# do full compile if running on main - this populates the cache
if : ${{ github.event_name != 'pull_request' }}
shell: bash
run: codeql query compile -j0 */ql/src --keep-going --warnings=error

View File

@@ -1,27 +0,0 @@
name: "Swift: Build and test Xcode autobuilder"
on:
pull_request:
paths:
- "swift/xcode-autobuilder/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-autobuilder.yml
branches:
- main
jobs:
autobuilder:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v4
with:
python-version-file: 'swift/.python-version'
- name: Build the Xcode autobuilder
run: |
bazel build //swift/xcode-autobuilder
- name: Test the Xcode autobuilder
run: |
bazel test //swift/xcode-autobuilder/tests

View File

@@ -1,44 +0,0 @@
name: "Swift: Check code generation"
on:
pull_request:
paths:
- "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-codegen.yml
- .github/actions/fetch-codeql/action.yml
branches:
- main
defaults:
run:
working-directory: swift
jobs:
codegen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v4
with:
python-version-file: 'swift/.python-version'
- uses: pre-commit/action@v3.0.0
name: Check that python code is properly formatted
with:
extra_args: autopep8 --all-files
- name: Run unit tests
run: |
bazel test //swift/codegen/test --test_output=errors
- uses: pre-commit/action@v3.0.0
name: Check that QL generated code was checked in
with:
extra_args: swift-codegen --all-files
- name: Generate C++ files
run: |
bazel run //swift/codegen:codegen -- --generate=trap,cpp --cpp-output=$PWD/swift-generated-cpp-files
- uses: actions/upload-artifact@v3
with:
name: swift-generated-cpp-files
path: swift-generated-cpp-files/**

View File

@@ -1,47 +0,0 @@
name: "Swift: Run Integration Tests"
on:
pull_request:
paths:
- "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-integration-tests.yml
- .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml
branches:
- main
defaults:
run:
working-directory: swift
jobs:
integration-tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
# - macos-latest TODO
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v4
with:
python-version-file: 'swift/.python-version'
- name: Build Swift extractor
run: |
bazel run //swift:create-extractor-pack
- name: Get Swift version
id: get_swift_version
run: |
VERSION=$(bazel run //swift/extractor -- --version | sed -ne 's/.*version \(\S*\).*/\1/p')
echo "::set-output name=version::$VERSION"
- uses: swift-actions/setup-swift@v1
with:
swift-version: "${{steps.get_swift_version.outputs.version}}"
- name: Run integration tests
run: |
python integration-tests/runner.py

View File

@@ -1,57 +0,0 @@
name: "Swift: Run QL Tests"
on:
pull_request:
paths:
- "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-qltest.yml
- .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml
branches:
- main
defaults:
run:
working-directory: swift
jobs:
qlformat:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
qltest-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v4
with:
python-version-file: 'swift/.python-version'
- name: Test qltest.sh
run: |
bazel test //swift/tools/test/qltest
qltest:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-20.04, macos-latest ]
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v4
with:
python-version-file: 'swift/.python-version'
- name: Build Swift extractor
run: |
bazel run //swift:create-extractor-pack
- name: Run QL tests
run: |
codeql test run --threads=0 --ram 5000 --search-path "${{ github.workspace }}/swift/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition ql/test
env:
GITHUB_TOKEN: ${{ github.token }}

121
.github/workflows/swift.yml vendored Normal file
View File

@@ -0,0 +1,121 @@
name: "Swift"
on:
pull_request:
paths:
- "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift.yml
- .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml
- .pre-commit-config.yaml
- "!**/*.md"
- "!**/*.qhelp"
branches:
- main
jobs:
changes:
runs-on: ubuntu-latest
outputs:
codegen: ${{ steps.filter.outputs.codegen }}
ql: ${{ steps.filter.outputs.ql }}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50
id: filter
with:
filters: |
codegen:
- 'github/workflows/swift.yml'
- "misc/bazel/**"
- "*.bazel*"
- 'swift/actions/setup-env/**'
- '.pre-commit-config.yaml'
- 'swift/codegen/**'
- 'swift/schema.py'
- 'swift/**/*.dbscheme'
- 'swift/ql/lib/codeql/swift/elements.qll'
- 'swift/ql/lib/codeql/swift/elements/**'
- 'swift/ql/lib/codeql/swift/generated/**'
- 'swift/ql/test/extractor-tests/generated/**'
ql:
- 'github/workflows/swift.yml'
- 'swift/**/*.ql'
- 'swift/**/*.qll'
# not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks
# without waiting for the macOS build
build-and-test-macos:
runs-on: macos-12-xl
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/create-extractor-pack
- uses: ./swift/actions/run-quick-tests
build-and-test-linux:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/create-extractor-pack
- uses: ./swift/actions/run-quick-tests
qltests-linux:
needs: build-and-test-linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/run-ql-tests
qltests-macos:
needs: build-and-test-macos
runs-on: macos-12-xl
strategy:
fail-fast: false
matrix:
slice: ["1/2", "2/2"]
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/run-ql-tests
with:
flags: --slice ${{ matrix.slice }}
integration-tests-linux:
needs: build-and-test-linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/run-integration-tests
integration-tests-macos:
needs: build-and-test-macos
runs-on: macos-12-xl
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/run-integration-tests
codegen:
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.codegen == 'true' }}
steps:
- uses: actions/checkout@v3
- uses: ./swift/actions/setup-env
- uses: pre-commit/action@v3.0.0
name: Check that python code is properly formatted
with:
extra_args: autopep8 --all-files
- uses: ./.github/actions/fetch-codeql
- uses: pre-commit/action@v3.0.0
name: Check that QL generated code was checked in
with:
extra_args: swift-codegen --all-files
- name: Generate C++ files
run: |
bazel run //swift/codegen:codegen -- --generate=trap,cpp --cpp-output=$PWD/generated-cpp-files
- uses: actions/upload-artifact@v3
with:
name: swift-generated-cpp-files
path: swift/generated-cpp-files/**
qlformat:
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.ql == 'true' }}
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- name: Check QL formatting
run: find swift/ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only

View File

@@ -31,7 +31,7 @@ repos:
- id: sync-files
name: Fix files required to be identical
files: \.(qll?|qhelp|swift)$
files: \.(qll?|qhelp|swift)$|^config/identical-files\.json$
language: system
entry: python3 config/sync-files.py --latest
pass_filenames: false

View File

@@ -40,6 +40,7 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
# Workflows
/.github/workflows/ @github/codeql-ci-reviewers
/.github/workflows/atm-* @github/codeql-ml-powered-queries-reviewers
/.github/workflows/go-* @github/codeql-go
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers

View File

@@ -17,6 +17,7 @@ provide:
# - "javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/test/qlpack.yml"
- "csharp/ql/campaigns/Solorigate/lib/qlpack.yml"
- "csharp/ql/campaigns/Solorigate/src/qlpack.yml"
- "csharp/ql/campaigns/Solorigate/test/qlpack.yml"

View File

@@ -600,8 +600,12 @@
"swift/ql/test/extractor-tests/patterns/patterns.swift",
"swift/ql/test/library-tests/ast/patterns.swift"
],
"Swift control flow test file": [
"swift/ql/test/library-tests/controlflow/graph/cfg.swift",
"swift/ql/test/library-tests/ast/cfg.swift"
],
"IncompleteMultiCharacterSanitization JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll",
"ruby/ql/lib/codeql/ruby/security/IncompleteMultiCharacterSanitizationQuery.qll"
]
}
}

View File

@@ -3,4 +3,4 @@ groups:
- cpp
- examples
dependencies:
codeql/cpp-all: "*"
codeql/cpp-all: ${workspace}

View File

@@ -1,3 +1,9 @@
## 0.4.3
### Minor Analysis Improvements
* Fixed bugs in the `FormatLiteral` class that were causing `getMaxConvertedLength` and related predicates to return no results when the format literal was `%e`, `%f` or `%g` and an explicit precision was specified.
## 0.4.2
No user-facing changes.

View File

@@ -1,4 +1,5 @@
---
category: minorAnalysis
---
## 0.4.3
### Minor Analysis Improvements
* Fixed bugs in the `FormatLiteral` class that were causing `getMaxConvertedLength` and related predicates to return no results when the format literal was `%e`, `%f` or `%g` and an explicit precision was specified.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.2
lastReleaseVersion: 0.4.3

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -1,9 +1,9 @@
name: codeql/cpp-all
version: 0.4.3-dev
version: 0.4.4-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
library: true
upgrades: upgrades
dependencies:
codeql/ssa: 0.0.1
codeql/ssa: ${workspace}

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -98,16 +98,16 @@ class ParameterPosition = Position;
/** An argument position represented by an integer. */
class ArgumentPosition = Position;
class Position extends TPosition {
abstract class Position extends TPosition {
abstract string toString();
}
class DirectPosition extends TDirectPosition {
class DirectPosition extends Position, TDirectPosition {
int index;
DirectPosition() { this = TDirectPosition(index) }
string toString() {
override string toString() {
index = -1 and
result = "this"
or
@@ -118,12 +118,12 @@ class DirectPosition extends TDirectPosition {
int getIndex() { result = index }
}
class IndirectionPosition extends TIndirectionPosition {
class IndirectionPosition extends Position, TIndirectionPosition {
int index;
IndirectionPosition() { this = TIndirectionPosition(index) }
string toString() {
override string toString() {
index = -1 and
result = "this"
or

View File

@@ -1,3 +1,9 @@
## 0.4.3
### Minor Analysis Improvements
* Fixed a bug in `cpp/jsf/av-rule-76` that caused the query to miss results when an implicitly-defined copy constructor or copy assignment operator was generated.
## 0.4.2
### New Queries

View File

@@ -0,0 +1,5 @@
## 0.4.3
### Minor Analysis Improvements
* Fixed a bug in `cpp/jsf/av-rule-76` that caused the query to miss results when an implicitly-defined copy constructor or copy assignment operator was generated.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.2
lastReleaseVersion: 0.4.3

View File

@@ -38,9 +38,9 @@ predicate hasNontrivialDestructor(Class c) {
from Class c
where
(hasPointerMember(c) or hasNontrivialDestructor(c)) and
not (
c.getAMemberFunction() instanceof CopyConstructor and
c.getAMemberFunction() instanceof CopyAssignmentOperator
(
c.hasImplicitCopyAssignmentOperator() or
c.hasImplicitCopyConstructor()
) and
not c instanceof Struct
select c,

View File

@@ -1,11 +1,11 @@
name: codeql/cpp-queries
version: 0.4.3-dev
version: 0.4.4-dev
groups:
- cpp
- queries
dependencies:
codeql/cpp-all: "*"
codeql/suite-helpers: "*"
codeql/cpp-all: ${workspace}
codeql/suite-helpers: ${workspace}
suites: codeql-suites
extractor: cpp
defaultSuiteFile: codeql-suites/cpp-code-scanning.qls

View File

@@ -2,43 +2,21 @@ edges
| test.cpp:4:15:4:20 | call to malloc | test.cpp:5:15:5:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store |
@@ -116,7 +94,6 @@ edges
| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
@@ -139,62 +116,30 @@ edges
| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:11:16:11:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:16:15:16:20 | call to malloc | test.cpp:17:15:17:15 | Load |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:28:15:28:20 | call to malloc | test.cpp:29:15:29:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store |
@@ -272,7 +217,6 @@ edges
| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
@@ -295,49 +239,25 @@ edges
| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:35:16:35:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:40:15:40:20 | call to malloc | test.cpp:41:15:41:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store |
@@ -415,7 +335,6 @@ edges
| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
@@ -438,8 +357,6 @@ edges
| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:47:16:47:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:62:39:62:39 | Load |
| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:66:39:66:39 | Load |
@@ -449,18 +366,13 @@ edges
| test.cpp:52:19:52:24 | call to malloc | test.cpp:53:12:53:16 | Load |
| test.cpp:53:5:53:23 | Store | test.cpp:51:33:51:35 | Load indirection |
| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store |
| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store |
| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... |
| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... |
| test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | Load indirection |
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:62:32:62:34 | Load |
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:66:32:66:34 | Load |
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:70:31:70:33 | Load |
| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:91:20:91:22 | arr indirection [begin] |
| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:95:20:95:22 | arr indirection [begin] |
@@ -479,8 +391,6 @@ edges
| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin |
| test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | Store |
| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store |
| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store |
| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... |
| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... |
| test.cpp:83:19:83:23 | begin | test.cpp:83:19:83:23 | Load |
| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:24:91:28 | begin |
@@ -488,21 +398,18 @@ edges
| test.cpp:91:24:91:28 | begin | test.cpp:91:47:91:47 | Load |
| test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end |
| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:91:40:91:42 | end | test.cpp:91:40:91:42 | Load |
| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:24:95:28 | begin |
| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:47:95:47 | Load |
| test.cpp:95:24:95:28 | begin | test.cpp:95:47:95:47 | Load |
| test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end |
| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:95:40:95:42 | end | test.cpp:95:40:95:42 | Load |
| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:24:99:28 | begin |
| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:46:99:46 | Load |
| test.cpp:99:24:99:28 | begin | test.cpp:99:46:99:46 | Load |
| test.cpp:99:35:99:37 | arr indirection [end] | test.cpp:99:39:99:41 | end |
| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:99:39:99:41 | end | test.cpp:99:39:99:41 | Load |
| test.cpp:104:27:104:29 | arr [begin] | test.cpp:105:20:105:22 | arr indirection [begin] |
| test.cpp:104:27:104:29 | arr [begin] | test.cpp:109:20:109:22 | arr indirection [begin] |
@@ -515,21 +422,18 @@ edges
| test.cpp:105:24:105:28 | begin | test.cpp:105:47:105:47 | Load |
| test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end |
| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:105:40:105:42 | end | test.cpp:105:40:105:42 | Load |
| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:24:109:28 | begin |
| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:47:109:47 | Load |
| test.cpp:109:24:109:28 | begin | test.cpp:109:47:109:47 | Load |
| test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end |
| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:109:40:109:42 | end | test.cpp:109:40:109:42 | Load |
| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:24:113:28 | begin |
| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:46:113:46 | Load |
| test.cpp:113:24:113:28 | begin | test.cpp:113:46:113:46 | Load |
| test.cpp:113:35:113:37 | arr indirection [end] | test.cpp:113:39:113:41 | end |
| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:113:39:113:41 | end | test.cpp:113:39:113:41 | Load |
| test.cpp:119:18:119:25 | call to mk_array [begin] | test.cpp:104:27:104:29 | arr [begin] |
| test.cpp:119:18:119:25 | call to mk_array [end] | test.cpp:104:27:104:29 | arr [end] |
@@ -558,8 +462,6 @@ edges
| test.cpp:144:16:144:18 | Load indirection [begin] | test.cpp:144:21:144:25 | begin |
| test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | Store |
| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store |
| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store |
| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... |
| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... |
| test.cpp:144:21:144:25 | begin | test.cpp:144:21:144:25 | Load |
| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:152:20:152:22 | Load indirection [begin] |
@@ -574,7 +476,6 @@ edges
| test.cpp:156:25:156:29 | begin | test.cpp:156:49:156:49 | Load |
| test.cpp:156:37:156:39 | Load indirection [end] | test.cpp:156:42:156:44 | end |
| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... |
| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... |
| test.cpp:156:42:156:44 | end | test.cpp:156:42:156:44 | Load |
| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:25:160:29 | begin |
| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:48:160:48 | Load |
@@ -590,21 +491,18 @@ edges
| test.cpp:166:25:166:29 | begin | test.cpp:166:49:166:49 | Load |
| test.cpp:166:37:166:39 | Load indirection [end] | test.cpp:166:42:166:44 | end |
| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:166:42:166:44 | end | test.cpp:166:42:166:44 | Load |
| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:25:170:29 | begin |
| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:49:170:49 | Load |
| test.cpp:170:25:170:29 | begin | test.cpp:170:49:170:49 | Load |
| test.cpp:170:37:170:39 | Load indirection [end] | test.cpp:170:42:170:44 | end |
| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:170:42:170:44 | end | test.cpp:170:42:170:44 | Load |
| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:25:174:29 | begin |
| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:48:174:48 | Load |
| test.cpp:174:25:174:29 | begin | test.cpp:174:48:174:48 | Load |
| test.cpp:174:36:174:38 | Load indirection [end] | test.cpp:174:41:174:43 | end |
| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:174:41:174:43 | end | test.cpp:174:41:174:43 | Load |
| test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | test.cpp:165:29:165:31 | arr indirection [begin] |
| test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | test.cpp:165:29:165:31 | arr indirection [end] |
@@ -614,19 +512,9 @@ edges
| test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:5 | Load |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store |
| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store |
| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load |
| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load |
| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load |
| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load |
| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array |
| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array |
| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array |
| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array |
| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | Store |
| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | Store |
@@ -637,29 +525,15 @@ edges
| test.cpp:195:17:195:23 | Store | test.cpp:201:5:201:19 | Store: ... = ... |
| test.cpp:195:17:195:23 | Store | test.cpp:201:5:201:19 | Store: ... = ... |
| test.cpp:197:20:197:22 | Load | test.cpp:201:5:201:19 | Store: ... = ... |
| test.cpp:197:20:197:22 | Load | test.cpp:201:5:201:19 | Store: ... = ... |
| test.cpp:201:5:201:12 | access to array | test.cpp:201:5:201:19 | Store: ... = ... |
| test.cpp:201:5:201:12 | access to array | test.cpp:201:5:201:19 | Store: ... = ... |
| test.cpp:205:23:205:28 | call to malloc | test.cpp:206:17:206:17 | Load |
| test.cpp:205:23:205:28 | call to malloc | test.cpp:208:15:208:15 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store |
| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store |
| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... |
| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... |
| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... |
| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... |
| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load |
| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load |
| test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | Store |
@@ -671,8 +545,6 @@ edges
| test.cpp:206:17:206:23 | Store | test.cpp:213:5:213:13 | Store: ... = ... |
| test.cpp:206:17:206:23 | Store | test.cpp:213:5:213:13 | Store: ... = ... |
| test.cpp:209:12:209:14 | Load | test.cpp:213:5:213:13 | Store: ... = ... |
| test.cpp:209:12:209:14 | Load | test.cpp:213:5:213:13 | Store: ... = ... |
| test.cpp:213:5:213:6 | * ... | test.cpp:213:5:213:13 | Store: ... = ... |
| test.cpp:213:5:213:6 | * ... | test.cpp:213:5:213:13 | Store: ... = ... |
| test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:6 | * ... |
| test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:13 | Store: ... = ... |

View File

@@ -329,21 +329,21 @@ namespace NestedTests {
namespace FlowThroughGlobals {
int globalVar;
int taintGlobal() {
void taintGlobal() {
globalVar = source();
}
int f() {
void f() {
sink(globalVar); // $ ir=333:17 ir=347:17 // tainted or clean? Not sure.
taintGlobal();
sink(globalVar); // $ ir=333:17 ir=347:17 MISSING: ast
}
int calledAfterTaint() {
void calledAfterTaint() {
sink(globalVar); // $ ir=333:17 ir=347:17 MISSING: ast
}
int taintAndCall() {
void taintAndCall() {
globalVar = source();
calledAfterTaint();
sink(globalVar); // $ ast ir=333:17 ir=347:17

View File

@@ -77,27 +77,9 @@ module IRTest {
)
}
override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
exists(GlobalOrNamespaceVariable var | var.getName().matches("flowTestGlobal%") |
writesVariable(n1.asInstruction(), var) and
var = n2.asVariable()
or
readsVariable(n2.asInstruction(), var) and
var = n1.asVariable()
)
}
override predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::InstructionBarrierGuard<testBarrierGuard/3>::getABarrierNode()
}
}
private predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
private predicate writesVariable(StoreInstruction store, Variable var) {
store.getDestinationAddress().(VariableAddressInstruction).getAstVariable() = var
}
}

View File

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

View File

@@ -1,7 +1,7 @@
name: codeql/cpp-tests
groups: [cpp, test]
dependencies:
codeql/cpp-all: "*"
codeql/cpp-queries: "*"
codeql/cpp-all: ${workspace}
codeql/cpp-queries: ${workspace}
extractor: cpp
tests: .

View File

@@ -12,11 +12,8 @@ nodes
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | semmle.label | ... + ... |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | semmle.label | fgets output argument |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection |
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection |
#select
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | This argument to a file access function is derived from $@ and then passed to fopen(filename). | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | user input (fgets) |

View File

@@ -12,11 +12,8 @@ nodes
| test.c:9:23:9:26 | argv | semmle.label | argv |
| test.c:9:23:9:26 | argv | semmle.label | argv |
| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... |
| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... |
| test.c:17:11:17:18 | fileName | semmle.label | fileName |
| test.c:17:11:17:18 | fileName | semmle.label | fileName |
| test.c:17:11:17:18 | fileName | semmle.label | fileName |
| test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection |
| test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection |
#select
| test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | 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:9:23:9:26 | argv | user input (argv) |

View File

@@ -29,18 +29,13 @@ nodes
| search.c:14:24:14:28 | *query | semmle.label | *query |
| search.c:14:24:14:28 | query | semmle.label | query |
| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... |
| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... |
| search.c:17:8:17:12 | query | semmle.label | query |
| search.c:17:8:17:12 | query | semmle.label | query |
| search.c:17:8:17:12 | query | semmle.label | query |
| search.c:17:8:17:12 | query indirection | semmle.label | query indirection |
| search.c:17:8:17:12 | query indirection | semmle.label | query indirection |
| search.c:22:24:22:28 | *query | semmle.label | *query |
| search.c:22:24:22:28 | query | semmle.label | query |
| search.c:23:39:23:43 | query | semmle.label | query |
| search.c:23:39:23:43 | query | semmle.label | query |
| search.c:23:39:23:43 | query | semmle.label | query |
| search.c:23:39:23:43 | query indirection | semmle.label | query indirection |
| search.c:23:39:23:43 | query indirection | semmle.label | query indirection |
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |

View File

@@ -18,18 +18,13 @@ nodes
| test.c:15:20:15:23 | argv | semmle.label | argv |
| test.c:15:20:15:23 | argv | semmle.label | argv |
| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... |
| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... |
| test.c:21:18:21:23 | query1 | semmle.label | query1 |
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
#select
| test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:15:20:15:23 | argv | user input (argv) |

View File

@@ -17,11 +17,8 @@ nodes
| test.cpp:37:73:37:76 | *data | semmle.label | *data |
| test.cpp:37:73:37:76 | data | semmle.label | data |
| test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... |
| test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |

View File

@@ -79,15 +79,11 @@ nodes
| test.cpp:24:30:24:36 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection |
| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection |
| test.cpp:29:30:29:36 | *command | semmle.label | *command |
| test.cpp:29:30:29:36 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
| test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... |
@@ -100,54 +96,36 @@ nodes
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
| test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:62:10:62:15 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:62:10:62:15 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) |
| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
| test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
| test.cpp:98:17:98:22 | recv output argument | semmle.label | recv output argument |
| test.cpp:99:15:99:20 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:99:15:99:20 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
| test.cpp:106:17:106:22 | recv output argument | semmle.label | recv output argument |
| test.cpp:107:15:107:20 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:107:15:107:20 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection |
#select
| test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:23 | call to getenv | call to getenv |
| test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:23 | call to getenv | call to getenv |

View File

@@ -56,42 +56,30 @@ nodes
| tests.c:28:22:28:25 | argv | semmle.label | argv |
| tests.c:28:22:28:25 | argv | semmle.label | argv |
| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... |
| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... |
| tests.c:28:22:28:28 | access to array | semmle.label | access to array |
| tests.c:28:22:28:28 | access to array | semmle.label | access to array |
| tests.c:28:22:28:28 | access to array | semmle.label | access to array |
| tests.c:28:22:28:28 | access to array indirection | semmle.label | access to array indirection |
| tests.c:28:22:28:28 | access to array indirection | semmle.label | access to array indirection |
| tests.c:29:28:29:31 | argv | semmle.label | argv |
| tests.c:29:28:29:31 | argv | semmle.label | argv |
| tests.c:29:28:29:34 | access to array | semmle.label | access to array |
| tests.c:29:28:29:34 | access to array | semmle.label | access to array |
| tests.c:29:28:29:34 | access to array | semmle.label | access to array |
| tests.c:29:28:29:34 | access to array indirection | semmle.label | access to array indirection |
| tests.c:29:28:29:34 | access to array indirection | semmle.label | access to array indirection |
| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion |
| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion |
| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 |
| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 |
| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 |
| tests.c:31:15:31:23 | buffer100 indirection | semmle.label | buffer100 indirection |
| tests.c:31:15:31:23 | buffer100 indirection | semmle.label | buffer100 indirection |
| tests.c:31:15:31:23 | scanf output argument | semmle.label | scanf output argument |
| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion |
| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion |
| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 |
| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 |
| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 |
| tests.c:33:21:33:29 | buffer100 indirection | semmle.label | buffer100 indirection |
| tests.c:33:21:33:29 | buffer100 indirection | semmle.label | buffer100 indirection |
| tests.c:34:10:34:13 | argv | semmle.label | argv |
| tests.c:34:10:34:13 | argv | semmle.label | argv |
| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... |
| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... |
| tests.c:34:10:34:16 | access to array | semmle.label | access to array |
| tests.c:34:10:34:16 | access to array | semmle.label | access to array |
| tests.c:34:10:34:16 | access to array | semmle.label | access to array |
| tests.c:34:10:34:16 | access to array indirection | semmle.label | access to array indirection |
| tests.c:34:10:34:16 | access to array indirection | semmle.label | access to array indirection |
#select
| tests.c:28:3:28:9 | call to sprintf | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |

View File

@@ -27,26 +27,18 @@ nodes
| char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | semmle.label | ... + ... |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | semmle.label | data indirection |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | semmle.label | data indirection |
| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | semmle.label | ... + ... |
| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | semmle.label | fgets output argument |
| char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | semmle.label | (const char *)... |
| char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | semmle.label | (const char *)... |
| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data |
| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data |
| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data |
| char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | semmle.label | data indirection |
| char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | semmle.label | data indirection |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv |
| char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | semmle.label | (const char *)... |
| char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | semmle.label | (const char *)... |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | semmle.label | data indirection |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | semmle.label | data indirection |
#select
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | The value of this argument may come from $@ and is being used as a formatting argument to badVaSink(data), which calls vsnprintf(format). | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | recv |

View File

@@ -272,29 +272,20 @@ nodes
| argvLocal.c:95:9:95:12 | argv | semmle.label | argv |
| argvLocal.c:95:9:95:12 | argv | semmle.label | argv |
| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array |
| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array |
| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array |
| argvLocal.c:95:9:95:15 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:95:9:95:15 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:96:15:96:18 | argv | semmle.label | argv |
| argvLocal.c:96:15:96:18 | argv | semmle.label | argv |
| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array |
| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array |
| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array |
| argvLocal.c:96:15:96:21 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:96:15:96:21 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:100:7:100:10 | argv | semmle.label | argv |
| argvLocal.c:100:7:100:10 | argv | semmle.label | argv |
| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 |
| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 |
| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 |
| argvLocal.c:101:9:101:10 | i1 indirection | semmle.label | i1 indirection |
| argvLocal.c:101:9:101:10 | i1 indirection | semmle.label | i1 indirection |
| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 |
| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 |
| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 |
| argvLocal.c:102:15:102:16 | i1 indirection | semmle.label | i1 indirection |
@@ -303,51 +294,35 @@ nodes
| argvLocal.c:105:14:105:17 | argv | semmle.label | argv |
| argvLocal.c:105:14:105:17 | argv | semmle.label | argv |
| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array |
| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array |
| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array |
| argvLocal.c:106:9:106:13 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:106:9:106:13 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array |
| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array |
| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array |
| argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:107:15:107:19 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... |
| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... |
| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... |
| argvLocal.c:110:9:110:11 | * ... indirection | semmle.label | * ... indirection |
| argvLocal.c:110:9:110:11 | * ... indirection | semmle.label | * ... indirection |
| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... |
| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... |
| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... |
| argvLocal.c:111:15:111:17 | * ... indirection | semmle.label | * ... indirection |
| argvLocal.c:111:15:111:17 | * ... indirection | semmle.label | * ... indirection |
| argvLocal.c:115:13:115:16 | argv | semmle.label | argv |
| argvLocal.c:115:13:115:16 | argv | semmle.label | argv |
| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 |
| argvLocal.c:116:9:116:10 | i3 indirection | semmle.label | i3 indirection |
| argvLocal.c:116:9:116:10 | i3 indirection | semmle.label | i3 indirection |
| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 |
| argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection |
| argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection |
| argvLocal.c:117:15:117:16 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection |
| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 indirection | semmle.label | i4 indirection |
@@ -356,108 +331,69 @@ nodes
| argvLocal.c:126:10:126:13 | argv | semmle.label | argv |
| argvLocal.c:126:10:126:13 | argv | semmle.label | argv |
| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 |
| argvLocal.c:127:9:127:10 | i5 indirection | semmle.label | i5 indirection |
| argvLocal.c:127:9:127:10 | i5 indirection | semmle.label | i5 indirection |
| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 |
| argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection |
| argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection |
| argvLocal.c:128:15:128:16 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:131:9:131:14 | ... + ... indirection | semmle.label | ... + ... indirection |
| argvLocal.c:131:9:131:14 | ... + ... indirection | semmle.label | ... + ... indirection |
| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:132:15:132:20 | ... + ... indirection | semmle.label | ... + ... indirection |
| argvLocal.c:132:15:132:20 | ... + ... indirection | semmle.label | ... + ... indirection |
| argvLocal.c:135:9:135:10 | i4 | semmle.label | i4 |
| argvLocal.c:135:9:135:10 | i4 | semmle.label | i4 |
| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ |
| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ |
| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ |
| argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection |
| argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection |
| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... |
| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... |
| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... |
| argvLocal.c:136:15:136:18 | -- ... indirection | semmle.label | -- ... indirection |
| argvLocal.c:136:15:136:18 | -- ... indirection | semmle.label | -- ... indirection |
| argvLocal.c:136:17:136:18 | i4 | semmle.label | i4 |
| argvLocal.c:136:17:136:18 | i4 | semmle.label | i4 |
| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 |
| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 |
| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 |
| argvLocal.c:144:9:144:10 | i7 indirection | semmle.label | i7 indirection |
| argvLocal.c:144:9:144:10 | i7 indirection | semmle.label | i7 indirection |
| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 |
| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 |
| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 |
| argvLocal.c:145:15:145:16 | i7 indirection | semmle.label | i7 indirection |
| argvLocal.c:145:15:145:16 | i7 indirection | semmle.label | i7 indirection |
| argvLocal.c:149:11:149:14 | argv | semmle.label | argv |
| argvLocal.c:149:11:149:14 | argv | semmle.label | argv |
| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 |
| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 |
| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 |
| argvLocal.c:150:9:150:10 | i8 indirection | semmle.label | i8 indirection |
| argvLocal.c:150:9:150:10 | i8 indirection | semmle.label | i8 indirection |
| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 |
| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 |
| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 |
| argvLocal.c:151:15:151:16 | i8 indirection | semmle.label | i8 indirection |
| argvLocal.c:151:15:151:16 | i8 indirection | semmle.label | i8 indirection |
| argvLocal.c:156:23:156:26 | argv | semmle.label | argv |
| argvLocal.c:156:23:156:26 | argv | semmle.label | argv |
| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:157:9:157:10 | i9 | semmle.label | i9 |
| argvLocal.c:157:9:157:10 | i9 indirection | semmle.label | i9 indirection |
| argvLocal.c:157:9:157:10 | i9 indirection | semmle.label | i9 indirection |
| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 |
| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 |
| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 |
| argvLocal.c:158:15:158:16 | i9 indirection | semmle.label | i9 indirection |
| argvLocal.c:158:15:158:16 | i9 indirection | semmle.label | i9 indirection |
| argvLocal.c:163:22:163:25 | argv | semmle.label | argv |
| argvLocal.c:163:22:163:25 | argv | semmle.label | argv |
| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:164:9:164:11 | i91 | semmle.label | i91 |
| argvLocal.c:164:9:164:11 | i91 indirection | semmle.label | i91 indirection |
| argvLocal.c:164:9:164:11 | i91 indirection | semmle.label | i91 indirection |
| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 |
| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 |
| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 |
| argvLocal.c:165:15:165:17 | i91 indirection | semmle.label | i91 indirection |
| argvLocal.c:165:15:165:17 | i91 indirection | semmle.label | i91 indirection |
| argvLocal.c:168:18:168:21 | argv | semmle.label | argv |
| argvLocal.c:168:18:168:21 | argv | semmle.label | argv |
| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... |
| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... |
| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:169:9:169:20 | i10 indirection | semmle.label | i10 indirection |
| argvLocal.c:169:9:169:20 | i10 indirection | semmle.label | i10 indirection |
| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 |
| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 |
| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 |
| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... |
| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... |
| argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection |
| argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection |
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
#select

View File

@@ -83,70 +83,50 @@ nodes
| funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument |
| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 |
| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 |
| funcsLocal.c:17:9:17:10 | i1 indirection | semmle.label | i1 indirection |
| funcsLocal.c:17:9:17:10 | i1 indirection | semmle.label | i1 indirection |
| funcsLocal.c:26:8:26:9 | fgets output argument | semmle.label | fgets output argument |
| funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 |
| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 |
| funcsLocal.c:27:9:27:10 | i3 indirection | semmle.label | i3 indirection |
| funcsLocal.c:27:9:27:10 | i3 indirection | semmle.label | i3 indirection |
| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets |
| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets |
| funcsLocal.c:31:19:31:21 | fgets output argument | semmle.label | fgets output argument |
| funcsLocal.c:31:19:31:21 | i41 | semmle.label | i41 |
| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 |
| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 |
| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 |
| funcsLocal.c:32:9:32:10 | i4 indirection | semmle.label | i4 indirection |
| funcsLocal.c:32:9:32:10 | i4 indirection | semmle.label | i4 indirection |
| funcsLocal.c:36:7:36:8 | gets output argument | semmle.label | gets output argument |
| funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 |
| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 |
| funcsLocal.c:37:9:37:10 | i5 indirection | semmle.label | i5 indirection |
| funcsLocal.c:37:9:37:10 | i5 indirection | semmle.label | i5 indirection |
| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets |
| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets |
| funcsLocal.c:41:18:41:20 | gets output argument | semmle.label | gets output argument |
| funcsLocal.c:41:18:41:20 | i61 | semmle.label | i61 |
| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 |
| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 |
| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 |
| funcsLocal.c:42:9:42:10 | i6 indirection | semmle.label | i6 indirection |
| funcsLocal.c:42:9:42:10 | i6 indirection | semmle.label | i6 indirection |
| funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... |
| funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... |
| funcsLocal.c:46:7:46:9 | gets output argument | semmle.label | gets output argument |
| funcsLocal.c:47:9:47:11 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:47:9:47:11 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... |
| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... |
| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... |
| funcsLocal.c:47:9:47:11 | * ... indirection | semmle.label | * ... indirection |
| funcsLocal.c:47:9:47:11 | * ... indirection | semmle.label | * ... indirection |
| funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets |
| funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets |
| funcsLocal.c:53:9:53:11 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:53:9:53:11 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... |
| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... |
| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... |
| funcsLocal.c:53:9:53:11 | * ... indirection | semmle.label | * ... indirection |
| funcsLocal.c:53:9:53:11 | * ... indirection | semmle.label | * ... indirection |
| funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... |
| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 |
| funcsLocal.c:58:9:58:10 | e1 indirection | semmle.label | e1 indirection |
| funcsLocal.c:58:9:58:10 | e1 indirection | semmle.label | e1 indirection |
#select
| funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | i1 | fread |
| funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:26:8:26:9 | i3 | fgets |

View File

@@ -90,12 +90,10 @@ nodes
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection |
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection |
| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
@@ -106,12 +104,10 @@ nodes
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
@@ -120,12 +116,10 @@ nodes
| globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection |
#select
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |

View File

@@ -90,12 +90,10 @@ nodes
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection |
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection |
| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
@@ -106,12 +104,10 @@ nodes
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
@@ -120,12 +116,10 @@ nodes
| globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection |
#select
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |

View File

@@ -92,101 +92,68 @@ nodes
| ifs.c:61:8:61:11 | argv | semmle.label | argv |
| ifs.c:61:8:61:11 | argv | semmle.label | argv |
| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:62:9:62:10 | c7 | semmle.label | c7 |
| ifs.c:62:9:62:10 | c7 | semmle.label | c7 |
| ifs.c:62:9:62:10 | c7 | semmle.label | c7 |
| ifs.c:62:9:62:10 | c7 indirection | semmle.label | c7 indirection |
| ifs.c:62:9:62:10 | c7 indirection | semmle.label | c7 indirection |
| ifs.c:68:8:68:11 | argv | semmle.label | argv |
| ifs.c:68:8:68:11 | argv | semmle.label | argv |
| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:69:9:69:10 | c8 | semmle.label | c8 |
| ifs.c:69:9:69:10 | c8 | semmle.label | c8 |
| ifs.c:69:9:69:10 | c8 | semmle.label | c8 |
| ifs.c:69:9:69:10 | c8 indirection | semmle.label | c8 indirection |
| ifs.c:69:9:69:10 | c8 indirection | semmle.label | c8 indirection |
| ifs.c:74:8:74:11 | argv | semmle.label | argv |
| ifs.c:74:8:74:11 | argv | semmle.label | argv |
| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:75:9:75:10 | i1 | semmle.label | i1 |
| ifs.c:75:9:75:10 | i1 | semmle.label | i1 |
| ifs.c:75:9:75:10 | i1 | semmle.label | i1 |
| ifs.c:75:9:75:10 | i1 indirection | semmle.label | i1 indirection |
| ifs.c:75:9:75:10 | i1 indirection | semmle.label | i1 indirection |
| ifs.c:80:8:80:11 | argv | semmle.label | argv |
| ifs.c:80:8:80:11 | argv | semmle.label | argv |
| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:81:9:81:10 | i2 | semmle.label | i2 |
| ifs.c:81:9:81:10 | i2 | semmle.label | i2 |
| ifs.c:81:9:81:10 | i2 | semmle.label | i2 |
| ifs.c:81:9:81:10 | i2 indirection | semmle.label | i2 indirection |
| ifs.c:81:9:81:10 | i2 indirection | semmle.label | i2 indirection |
| ifs.c:86:8:86:11 | argv | semmle.label | argv |
| ifs.c:86:8:86:11 | argv | semmle.label | argv |
| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:87:9:87:10 | i3 | semmle.label | i3 |
| ifs.c:87:9:87:10 | i3 | semmle.label | i3 |
| ifs.c:87:9:87:10 | i3 | semmle.label | i3 |
| ifs.c:87:9:87:10 | i3 indirection | semmle.label | i3 indirection |
| ifs.c:87:9:87:10 | i3 indirection | semmle.label | i3 indirection |
| ifs.c:92:8:92:11 | argv | semmle.label | argv |
| ifs.c:92:8:92:11 | argv | semmle.label | argv |
| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:93:9:93:10 | i4 | semmle.label | i4 |
| ifs.c:93:9:93:10 | i4 | semmle.label | i4 |
| ifs.c:93:9:93:10 | i4 | semmle.label | i4 |
| ifs.c:93:9:93:10 | i4 indirection | semmle.label | i4 indirection |
| ifs.c:93:9:93:10 | i4 indirection | semmle.label | i4 indirection |
| ifs.c:98:8:98:11 | argv | semmle.label | argv |
| ifs.c:98:8:98:11 | argv | semmle.label | argv |
| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:99:9:99:10 | i5 | semmle.label | i5 |
| ifs.c:99:9:99:10 | i5 | semmle.label | i5 |
| ifs.c:99:9:99:10 | i5 | semmle.label | i5 |
| ifs.c:99:9:99:10 | i5 indirection | semmle.label | i5 indirection |
| ifs.c:99:9:99:10 | i5 indirection | semmle.label | i5 indirection |
| ifs.c:105:8:105:11 | argv | semmle.label | argv |
| ifs.c:105:8:105:11 | argv | semmle.label | argv |
| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:106:9:106:10 | i6 | semmle.label | i6 |
| ifs.c:106:9:106:10 | i6 | semmle.label | i6 |
| ifs.c:106:9:106:10 | i6 | semmle.label | i6 |
| ifs.c:106:9:106:10 | i6 indirection | semmle.label | i6 indirection |
| ifs.c:106:9:106:10 | i6 indirection | semmle.label | i6 indirection |
| ifs.c:111:8:111:11 | argv | semmle.label | argv |
| ifs.c:111:8:111:11 | argv | semmle.label | argv |
| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:112:9:112:10 | i7 | semmle.label | i7 |
| ifs.c:112:9:112:10 | i7 | semmle.label | i7 |
| ifs.c:112:9:112:10 | i7 | semmle.label | i7 |
| ifs.c:112:9:112:10 | i7 indirection | semmle.label | i7 indirection |
| ifs.c:112:9:112:10 | i7 indirection | semmle.label | i7 indirection |
| ifs.c:117:8:117:11 | argv | semmle.label | argv |
| ifs.c:117:8:117:11 | argv | semmle.label | argv |
| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:118:9:118:10 | i8 | semmle.label | i8 |
| ifs.c:118:9:118:10 | i8 | semmle.label | i8 |
| ifs.c:118:9:118:10 | i8 | semmle.label | i8 |
| ifs.c:118:9:118:10 | i8 indirection | semmle.label | i8 indirection |
| ifs.c:118:9:118:10 | i8 indirection | semmle.label | i8 indirection |
| ifs.c:123:8:123:11 | argv | semmle.label | argv |
| ifs.c:123:8:123:11 | argv | semmle.label | argv |
| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... |
| ifs.c:124:9:124:10 | i9 | semmle.label | i9 |
| ifs.c:124:9:124:10 | i9 | semmle.label | i9 |
| ifs.c:124:9:124:10 | i9 | semmle.label | i9 |
| ifs.c:124:9:124:10 | i9 indirection | semmle.label | i9 indirection |
| ifs.c:124:9:124:10 | i9 indirection | semmle.label | i9 indirection |
#select
| ifs.c:62:9:62:10 | c7 | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | ifs.c:61:8:61:11 | argv | argv |

View File

@@ -9,6 +9,5 @@ nodes
| examples.cpp:63:26:63:30 | fscanf output argument | semmle.label | fscanf output argument |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
#select
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | & ... | User-provided value |

View File

@@ -28,7 +28,6 @@ nodes
| test2.cpp:12:21:12:21 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:25:22:25:23 | & ... | semmle.label | & ... |
| test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument |
| test2.cpp:27:13:27:13 | v | semmle.label | v |
@@ -37,26 +36,21 @@ nodes
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test.c:11:29:11:32 | argv | semmle.label | argv |
| test.c:11:29:11:32 | argv | semmle.label | argv |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:41:17:41:20 | argv | semmle.label | argv |
| test.c:41:17:41:20 | argv | semmle.label | argv |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:51:17:51:20 | argv | semmle.label | argv |
| test.c:51:17:51:20 | argv | semmle.label | argv |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
#select
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |

View File

@@ -2,7 +2,7 @@
name: codeql/cpp-tests-cwe-190-tainted
groups: [cpp, test]
dependencies:
codeql/cpp-all: "*"
codeql/cpp-queries: "*"
codeql/cpp-all: ${workspace}
codeql/cpp-queries: ${workspace}
extractor: cpp
tests: .

View File

@@ -23,22 +23,16 @@ nodes
| test.cpp:16:25:16:42 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:20:14:20:20 | address | semmle.label | address |
| test.cpp:20:14:20:20 | address | semmle.label | address |
| test.cpp:20:14:20:20 | address | semmle.label | address |
| test.cpp:20:14:20:20 | address indirection | semmle.label | address indirection |
| test.cpp:20:14:20:20 | address indirection | semmle.label | address indirection |
| test.cpp:27:25:27:30 | call to getenv | semmle.label | call to getenv |
| test.cpp:27:25:27:42 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:31:14:31:20 | address | semmle.label | address |
| test.cpp:31:14:31:20 | address | semmle.label | address |
| test.cpp:31:14:31:20 | address | semmle.label | address |
| test.cpp:31:14:31:20 | address indirection | semmle.label | address indirection |
| test.cpp:31:14:31:20 | address indirection | semmle.label | address indirection |
| test.cpp:38:25:38:30 | call to getenv | semmle.label | call to getenv |
| test.cpp:38:25:38:42 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:42:14:42:20 | address | semmle.label | address |
| test.cpp:42:14:42:20 | address | semmle.label | address |
| test.cpp:42:14:42:20 | address | semmle.label | address |
| test.cpp:42:14:42:20 | address indirection | semmle.label | address indirection |
| test.cpp:42:14:42:20 | address indirection | semmle.label | address indirection |
#select
| test.cpp:20:7:20:12 | call to strcmp | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv |

View File

@@ -9,6 +9,5 @@ nodes
| test.cpp:20:29:20:47 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:24:10:24:35 | ! ... | semmle.label | ! ... |
| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp |
| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp |
#select
| test.cpp:24:10:24:35 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@. | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... |

View File

@@ -0,0 +1,3 @@
| test.cpp:5:7:5:12 | Class2 | AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors. |
| test.cpp:16:7:16:12 | Class3 | AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors. |
| test.cpp:33:7:33:12 | Class4 | AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors. |

View File

@@ -0,0 +1 @@
jsf/4.10 Classes/AV Rule 76.ql

View File

@@ -0,0 +1,96 @@
class Class1 // good: no pointer members, default assignment operator and copy constructor
{
};
class Class2 // bad: pointer members, default assignment operator and copy constructor
{
private:
int* _a;
public:
Class2(int* a):_a(a)
{
}
};
class Class3 // bad: pointer members, custom assignment operator and default copy constructor
{
private:
int* _a;
public:
Class3(int* a) :_a(a)
{
}
Class3& operator=(const Class3& rhs)
{
this->_a = rhs._a;
return *this;
}
};
class Class4 // bad: pointer members, default assignment operator and custom copy constructor
{
private:
int* _a;
public:
Class4(int* a) :_a(a)
{
}
Class4(const Class4& rhs):_a(rhs._a)
{
}
};
class Class5 // good: pointer members, custom assignment operator and copy constructor
{
private:
int* _a;
public:
Class5(int* a) :_a(a)
{
}
Class5(const Class5& rhs) :_a(rhs._a)
{
}
Class5& operator=(const Class5& rhs)
{
this->_a = rhs._a;
return *this;
}
};
class Class6 // good: pointer members, deleted assignment operator and copy constructor
{
private:
int* _a;
public:
Class6(int* a) :_a(a)
{
}
Class6& operator=(const Class6& rhs) = delete;
Class6(const Class6& rhs) = delete;
};
class Class7 // good: pointer members, disallowed assignment operator and copy constructor
{
private:
int* _a;
public:
Class7(int* a) :_a(a)
{
}
private:
Class7& operator=(const Class7& rhs); // no implementation to get linker error!
Class7(const Class7& rhs); // no implementation to get linker error!
};

View File

@@ -1,3 +1,7 @@
## 1.3.3
No user-facing changes.
## 1.3.2
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.3.2
lastReleaseVersion: 1.3.3

View File

@@ -1,8 +1,8 @@
name: codeql/csharp-solorigate-all
version: 1.3.3-dev
version: 1.3.4-dev
groups:
- csharp
- solorigate
library: true
dependencies:
codeql/csharp-all: "*"
codeql/csharp-all: ${workspace}

View File

@@ -1,3 +1,7 @@
## 1.3.3
No user-facing changes.
## 1.3.2
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.3.2
lastReleaseVersion: 1.3.3

View File

@@ -1,9 +1,9 @@
name: codeql/csharp-solorigate-queries
version: 1.3.3-dev
version: 1.3.4-dev
groups:
- csharp
- solorigate
defaultSuiteFile: codeql-suites/solorigate.qls
dependencies:
codeql/csharp-all: "*"
codeql/csharp-solorigate-all: "*"
codeql/csharp-all: ${workspace}
codeql/csharp-solorigate-all: ${workspace}

View File

@@ -4,9 +4,9 @@ groups:
- solorigate
- test
dependencies:
codeql/csharp-all: "*"
codeql/csharp-queries: "*"
codeql/csharp-solorigate-all: "*"
codeql/csharp-solorigate-queries: "*"
codeql/csharp-all: ${workspace}
codeql/csharp-queries: ${workspace}
codeql/csharp-solorigate-all: ${workspace}
codeql/csharp-solorigate-queries: ${workspace}
extractor: csharp
tests: .

View File

@@ -1,5 +1,5 @@
name: codeql-csharp-consistency-queries
groups: [csharp, test, consistency-queries]
dependencies:
codeql/csharp-all: "*"
codeql/csharp-all: ${workspace}
extractor: csharp

View File

@@ -3,4 +3,4 @@ groups:
- csharp
- examples
dependencies:
codeql/csharp-all: "*"
codeql/csharp-all: ${workspace}

View File

@@ -1,3 +1,7 @@
## 0.4.3
No user-facing changes.
## 0.4.2
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.2
lastReleaseVersion: 0.4.3

View File

@@ -1,9 +1,9 @@
name: codeql/csharp-all
version: 0.4.3-dev
version: 0.4.4-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
library: true
upgrades: upgrades
dependencies:
codeql/ssa: 0.0.1
codeql/ssa: ${workspace}

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa, Configuration config) {
evalUnfold(apa, false, config) and
result = 1 and
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
) {
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head, tail.(AccessPathNil).getType())
or
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
result = TCons1(head, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -2874,54 +2879,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
}
}
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source are generated.
*/
class PathNode extends TPathNode {
/** Gets a textual representation of this element. */
string toString() { none() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
abstract private class PathNodeImpl extends TPathNode {
/** Gets the `FlowState` of this node. */
FlowState getState() { none() }
abstract FlowState getState();
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
abstract Configuration getConfiguration();
/** Holds if this node is a source. */
predicate isSource() { none() }
}
abstract predicate isSource();
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2934,23 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
/** Gets a textual representation of this element. */
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
override predicate hasLocationInfo(
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2963,59 @@ private predicate directReach(PathNodeImpl n) {
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
*/
class PathNode instanceof PathNodeImpl {
PathNode() { reach(this) }
/** Gets a textual representation of this element. */
final string toString() { result = super.toString() }
/**
* Gets a textual representation of this element, including a textual
* representation of the call context.
*/
final string toStringWithContext() { result = super.toStringWithContext() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the underlying `Node`. */
final Node getNode() { super.getNodeEx().projectToNode() = result }
/** Gets the `FlowState` of this node. */
final FlowState getState() { result = super.getState() }
/** Gets the associated configuration. */
final Configuration getConfiguration() { result = super.getConfiguration() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3026,7 @@ module PathGraph {
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
key = "semmle.label" and val = n.toString()
}
/**
@@ -3013,11 +3035,7 @@ module PathGraph {
* `ret -> out` is summarized as the edge `arg -> out`.
*/
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
Subpaths::subpaths(arg, par, ret, out) and
reach(arg) and
reach(par) and
reach(ret) and
reach(out)
Subpaths::subpaths(arg, par, ret, out)
}
}
@@ -3142,6 +3160,7 @@ private predicate pathNode(
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
@@ -3399,7 +3418,7 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, FlowState sout, AccessPath apout
) {
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3407,14 +3426,14 @@ private module Subpaths {
}
pragma[nomagic]
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
*/
pragma[nomagic]
private predicate subpaths03(
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3463,7 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3479,7 @@ private module Subpaths {
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
retReach(mid) and
@@ -3477,11 +3496,12 @@ private module Subpaths {
* sinks.
*/
private predicate flowsTo(
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
Configuration configuration
) {
flowsource.isSource() and
flowsource.getConfiguration() = configuration and
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
}
@@ -3504,14 +3524,14 @@ private predicate finalStats(
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
tuples = count(PathNodeImpl pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
tuples = count(PathNode pn)
}
/**

View File

@@ -310,12 +310,27 @@ module LocalFlow {
* Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
* can reach `next`.
*/
private predicate localFlowSsaInput(Node nodeFrom, Ssa::Definition def, Ssa::Definition next) {
exists(ControlFlow::BasicBlock bb, int i | SsaImpl::lastRefBeforeRedef(def, bb, i, next) |
private predicate localFlowSsaInputFromDef(
Node nodeFrom, Ssa::Definition def, Ssa::Definition next
) {
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::lastRefBeforeRedef(def, bb, i, next) and
def.definesAt(_, bb, i) and
def = getSsaDefinition(nodeFrom)
or
nodeFrom.asExprAtNode(bb.getNode(i)) instanceof AssignableRead
)
}
/**
* Holds if `read` is a last node reading SSA definition `def`, which
* can reach `next`.
*/
predicate localFlowSsaInputFromExpr(
ControlFlow::Node read, Ssa::Definition def, Ssa::Definition next
) {
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::lastRefBeforeRedef(def, bb, i, next) and
read = bb.getNode(i) and
read.getElement() instanceof AssignableRead
)
}
@@ -351,18 +366,14 @@ module LocalFlow {
// Flow from read to next read
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
// Flow into phi node
exists(Ssa::PhiNode phi |
localFlowSsaInput(nodeFrom, def, phi) and
phi = nodeTo.(SsaDefinitionNode).getDefinition() and
def = phi.getAnInput()
)
or
// Flow into uncertain SSA definition
exists(LocalFlow::UncertainExplicitSsaDefinition uncertain |
localFlowSsaInput(nodeFrom, def, uncertain) and
uncertain = nodeTo.(SsaDefinitionNode).getDefinition() and
def = uncertain.getPriorDefinition()
// Flow into phi/uncertain SSA definition node from def
exists(Ssa::Definition next |
localFlowSsaInputFromDef(nodeFrom, def, next) and
next = nodeTo.(SsaDefinitionNode).getDefinition()
|
def = next.(Ssa::PhiNode).getAnInput()
or
def = next.(LocalFlow::UncertainExplicitSsaDefinition).getPriorDefinition()
)
}
@@ -519,11 +530,26 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
or
exists(Ssa::Definition def |
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom,
any(DataFlowSummarizedCallable sc)) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _) and
not LocalFlow::usesInstanceField(def)
)
or
// Flow into phi/uncertain SSA definition node from read
exists(Ssa::Definition def, ControlFlow::Node read, Ssa::Definition next |
LocalFlow::localFlowSsaInputFromExpr(read, def, next) and
next = nodeTo.(SsaDefinitionNode).getDefinition() and
def =
[
next.(Ssa::PhiNode).getAnInput(),
next.(LocalFlow::UncertainExplicitSsaDefinition).getPriorDefinition()
]
|
exists(nodeFrom.asExprAtNode(read)) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
or
exists(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExprAtNode(read))
)
or
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
@@ -859,6 +885,21 @@ private module Cached {
LocalFlow::usesInstanceField(def)
)
or
// Flow into phi/uncertain SSA definition node from read
exists(Ssa::Definition def, ControlFlow::Node read, Ssa::Definition next |
LocalFlow::localFlowSsaInputFromExpr(read, def, next) and
next = nodeTo.(SsaDefinitionNode).getDefinition() and
def =
[
next.(Ssa::PhiNode).getAnInput(),
next.(LocalFlow::UncertainExplicitSsaDefinition).getPriorDefinition()
]
|
exists(nodeFrom.asExprAtNode(read))
or
exists(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExprAtNode(read))
)
or
// Simple flow through library code is included in the exposed local
// step relation, even though flow is technically inter-procedural
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(nodeFrom, nodeTo,

View File

@@ -1,3 +1,7 @@
## 0.4.3
No user-facing changes.
## 0.4.2
No user-facing changes.

View File

@@ -1,6 +1,6 @@
/**
* @id cs/summary/lines-of-code
* @name Total lines of code in the database
* @name Total lines of C# code in the database
* @description The total number of lines of code across all files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.2
lastReleaseVersion: 0.4.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 0.4.3-dev
version: 0.4.4-dev
groups:
- csharp
- queries
@@ -7,5 +7,5 @@ suites: codeql-suites
extractor: csharp
defaultSuiteFile: codeql-suites/csharp-code-scanning.qls
dependencies:
codeql/csharp-all: "*"
codeql/suite-helpers: "*"
codeql/csharp-all: ${workspace}
codeql/suite-helpers: ${workspace}

View File

@@ -1 +1 @@
| test.cs:31:9:31:74 | call to method InitiateSystemShutdownExW | Call to an external method 'InitiateSystemShutdownExW'. |
| test.cs:32:9:32:74 | call to method InitiateSystemShutdownExW | Call to an external method 'InitiateSystemShutdownExW'. |

View File

@@ -1,23 +1,17 @@
edges
| test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:36:70:48 | access to local variable lastWriteTime |
| test.cs:70:13:70:71 | call to method CompareTo : Int32 | test.cs:70:13:70:76 | ... >= ... |
| test.cs:70:36:70:48 | access to local variable lastWriteTime | test.cs:70:36:70:70 | call to method AddHours |
| test.cs:70:36:70:48 | access to local variable lastWriteTime | test.cs:70:36:70:70 | call to method AddHours : DateTime |
| test.cs:70:36:70:48 | access to local variable lastWriteTime : DateTime | test.cs:70:36:70:70 | call to method AddHours |
| test.cs:70:36:70:48 | access to local variable lastWriteTime : DateTime | test.cs:70:36:70:70 | call to method AddHours : DateTime |
| test.cs:70:36:70:70 | call to method AddHours | test.cs:70:13:70:71 | call to method CompareTo |
| test.cs:70:36:70:70 | call to method AddHours | test.cs:70:13:70:71 | call to method CompareTo : Int32 |
| test.cs:70:36:70:70 | call to method AddHours : DateTime | test.cs:70:13:70:71 | call to method CompareTo |
| test.cs:70:36:70:70 | call to method AddHours : DateTime | test.cs:70:13:70:71 | call to method CompareTo : Int32 |
| test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:36:71:48 | access to local variable lastWriteTime |
| test.cs:71:13:71:71 | call to method CompareTo : Int32 | test.cs:71:13:71:76 | ... >= ... |
| test.cs:71:36:71:48 | access to local variable lastWriteTime | test.cs:71:36:71:70 | call to method AddHours |
| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:13:71:71 | call to method CompareTo |
| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:13:71:71 | call to method CompareTo : Int32 |
#select
| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:71 | call to method CompareTo | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:71 | call to method CompareTo : Int32 | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:76 | ... >= ... | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:76 | ... >= ... : Boolean | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:71 | call to method CompareTo | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:71 | call to method CompareTo : Int32 | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:76 | ... >= ... | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file |
nodes
| test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | semmle.label | call to method GetLastWriteTime : DateTime |
| test.cs:70:13:70:71 | call to method CompareTo | semmle.label | call to method CompareTo |
| test.cs:70:13:70:71 | call to method CompareTo : Int32 | semmle.label | call to method CompareTo : Int32 |
| test.cs:70:13:70:76 | ... >= ... | semmle.label | ... >= ... |
| test.cs:70:36:70:48 | access to local variable lastWriteTime | semmle.label | access to local variable lastWriteTime |
| test.cs:70:36:70:70 | call to method AddHours | semmle.label | call to method AddHours |
| test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | semmle.label | call to method GetLastWriteTime : DateTime |
| test.cs:71:13:71:71 | call to method CompareTo | semmle.label | call to method CompareTo |
| test.cs:71:13:71:71 | call to method CompareTo : Int32 | semmle.label | call to method CompareTo : Int32 |
| test.cs:71:13:71:76 | ... >= ... | semmle.label | ... >= ... |
| test.cs:71:36:71:48 | access to local variable lastWriteTime | semmle.label | access to local variable lastWriteTime |
| test.cs:71:36:71:70 | call to method AddHours | semmle.label | call to method AddHours |

View File

@@ -21,7 +21,8 @@ namespace System.Diagnostics
}
}
class External {
class External
{
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool InitiateSystemShutdownExW([In] string lpMachineName, [In] string lpMessage, [In] uint dwTimeout, [MarshalAs(UnmanagedType.Bool)][In] bool bForceAppsClosed, [MarshalAs(UnmanagedType.Bool)][In] bool bRebootAfterShutdown, [In] uint dwReason);
@@ -46,28 +47,28 @@ class External {
{
}
// regular FVN
return num;
return num;
}
void IndirectTestProcessNameToHashTaintFlow( string s)
void IndirectTestProcessNameToHashTaintFlow(string s)
{
GetFvnHash(s); // BUG : ProcessNameToHashTaintFlow
}
void TestProcessNameToHashTaintFlow()
{
GetFvnHash( System.Diagnostics.Process.GetCurrentProcess() ); // BUG : ProcessNameToHashTaintFlow
GetFvnHash(System.Diagnostics.Process.GetCurrentProcess()); // BUG : ProcessNameToHashTaintFlow
string proc = System.Diagnostics.Process.GetCurrentProcess();
IndirectTestProcessNameToHashTaintFlow( proc );
IndirectTestProcessNameToHashTaintFlow(proc);
}
void TestTimeBomb()
void TestTimeBomb()
{
DateTime lastWriteTime = System.IO.File.GetLastWriteTime("someFile");
int num = new Random().Next(288, 336);
if (DateTime.Now.CompareTo(lastWriteTime.AddHours((double)num)) >= 0) // BUG : Potential time bomb
if (DateTime.Now.CompareTo(lastWriteTime.AddHours((double)num)) >= 0) // BUG : Potential time bomb, currently not detected
{
// Some code here
}

View File

@@ -918,6 +918,14 @@ edges
| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | J.cs:106:14:106:17 | access to property X |
| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | J.cs:107:14:107:17 | access to property Y |
| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | J.cs:107:14:107:17 | access to property Y |
| J.cs:119:13:119:13 | [post] access to local variable a [element] : Int32 | J.cs:125:14:125:14 | access to local variable a [element] : Int32 |
| J.cs:119:13:119:13 | [post] access to local variable a [element] : Int32 | J.cs:125:14:125:14 | access to local variable a [element] : Int32 |
| J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | J.cs:119:13:119:13 | [post] access to local variable a [element] : Int32 |
| J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | J.cs:119:13:119:13 | [post] access to local variable a [element] : Int32 |
| J.cs:125:14:125:14 | access to local variable a [element] : Int32 | J.cs:125:14:125:17 | access to array element : Int32 |
| J.cs:125:14:125:14 | access to local variable a [element] : Int32 | J.cs:125:14:125:17 | access to array element : Int32 |
| J.cs:125:14:125:17 | access to array element : Int32 | J.cs:125:14:125:17 | (...) ... |
| J.cs:125:14:125:17 | access to array element : Int32 | J.cs:125:14:125:17 | (...) ... |
nodes
| A.cs:5:17:5:28 | call to method Source<C> : C | semmle.label | call to method Source<C> : C |
| A.cs:5:17:5:28 | call to method Source<C> : C | semmle.label | call to method Source<C> : C |
@@ -1925,6 +1933,16 @@ nodes
| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | semmle.label | access to local variable a3 [property Y] : Object |
| J.cs:107:14:107:17 | access to property Y | semmle.label | access to property Y |
| J.cs:107:14:107:17 | access to property Y | semmle.label | access to property Y |
| J.cs:119:13:119:13 | [post] access to local variable a [element] : Int32 | semmle.label | [post] access to local variable a [element] : Int32 |
| J.cs:119:13:119:13 | [post] access to local variable a [element] : Int32 | semmle.label | [post] access to local variable a [element] : Int32 |
| J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | semmle.label | call to method Source<Int32> : Int32 |
| J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | semmle.label | call to method Source<Int32> : Int32 |
| J.cs:125:14:125:14 | access to local variable a [element] : Int32 | semmle.label | access to local variable a [element] : Int32 |
| J.cs:125:14:125:14 | access to local variable a [element] : Int32 | semmle.label | access to local variable a [element] : Int32 |
| J.cs:125:14:125:17 | (...) ... | semmle.label | (...) ... |
| J.cs:125:14:125:17 | (...) ... | semmle.label | (...) ... |
| J.cs:125:14:125:17 | access to array element : Int32 | semmle.label | access to array element : Int32 |
| J.cs:125:14:125:17 | access to array element : Int32 | semmle.label | access to array element : Int32 |
subpaths
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
@@ -2101,3 +2119,4 @@ subpaths
| J.cs:102:14:102:17 | access to property X | J.cs:97:17:97:33 | call to method Source<Object> : Object | J.cs:102:14:102:17 | access to property X | $@ | J.cs:97:17:97:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:106:14:106:17 | access to property X | J.cs:97:17:97:33 | call to method Source<Object> : Object | J.cs:106:14:106:17 | access to property X | $@ | J.cs:97:17:97:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:107:14:107:17 | access to property Y | J.cs:105:32:105:48 | call to method Source<Object> : Object | J.cs:107:14:107:17 | access to property Y | $@ | J.cs:105:32:105:48 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| J.cs:125:14:125:17 | (...) ... | J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | J.cs:125:14:125:17 | (...) ... | $@ | J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | call to method Source<Int32> : Int32 |

View File

@@ -111,6 +111,35 @@ public class J
Sink(a4.Y); // no flow
}
private void M6(bool b)
{
var a = new int[1];
if (b)
{
a[0] = Source<int>(10);
}
else
{
a = new int[1];
}
Sink(a[0]); // $ hasValueFlow=10
}
private void M7(bool b)
{
var a = new System.Collections.Generic.List<int>();
if (b)
{
a.Add(Source<int>(11));
a.Clear();
}
else
{
a = new System.Collections.Generic.List<int>();
}
Sink(a[0]);
}
public static void Sink(object o) { }
static T Source<T>(object source) => throw null;

View File

@@ -65,6 +65,8 @@
| LocalDataFlow.cs:84:31:84:35 | [b (line 48): false] access to local variable sink6 | LocalDataFlow.cs:84:21:84:35 | [b (line 48): false] ... ? ... : ... |
| LocalDataFlow.cs:85:15:85:19 | [b (line 48): false] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:85:15:85:19 | [b (line 48): true] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:85:15:85:19 | [post] [b (line 48): false] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:85:15:85:19 | [post] [b (line 48): true] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:88:9:88:36 | SSA def(nonSink0) | LocalDataFlow.cs:89:15:89:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:88:20:88:36 | ... ? ... : ... | LocalDataFlow.cs:88:9:88:36 | SSA def(nonSink0) |
| LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) | LocalDataFlow.cs:92:29:92:33 | access to local variable sink7 |
@@ -484,7 +486,9 @@
| SSA.cs:37:24:37:31 | access to local variable ssaSink0 | SSA.cs:117:36:117:43 | access to local variable ssaSink0 |
| SSA.cs:38:17:38:26 | [post] access to parameter nonTainted | SSA.cs:47:13:47:22 | access to parameter nonTainted |
| SSA.cs:38:17:38:26 | access to parameter nonTainted | SSA.cs:47:13:47:22 | access to parameter nonTainted |
| SSA.cs:39:21:39:28 | [post] access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:39:21:39:28 | access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:41:21:41:28 | [post] access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:41:21:41:28 | access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:43:9:43:24 | SSA phi(ssaSink2) | SSA.cs:43:15:43:22 | access to local variable ssaSink2 |
| SSA.cs:46:16:46:28 | SSA def(nonSink2) | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
@@ -499,15 +503,19 @@
| SSA.cs:49:24:49:31 | access to local variable nonSink0 | SSA.cs:63:23:63:30 | access to local variable nonSink0 |
| SSA.cs:50:17:50:26 | [post] access to parameter nonTainted | SSA.cs:89:13:89:22 | access to parameter nonTainted |
| SSA.cs:50:17:50:26 | access to parameter nonTainted | SSA.cs:89:13:89:22 | access to parameter nonTainted |
| SSA.cs:51:21:51:28 | [post] access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:51:21:51:28 | access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:53:21:53:28 | [post] access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:53:21:53:28 | access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:55:9:55:24 | SSA phi(nonSink2) | SSA.cs:55:15:55:22 | access to local variable nonSink2 |
| SSA.cs:58:16:58:33 | SSA def(ssaSink3) | SSA.cs:59:23:59:30 | access to local variable ssaSink3 |
| SSA.cs:58:27:58:33 | access to parameter tainted | SSA.cs:58:16:58:33 | SSA def(ssaSink3) |
| SSA.cs:58:27:58:33 | access to parameter tainted | SSA.cs:67:32:67:38 | access to parameter tainted |
| SSA.cs:59:23:59:30 | SSA def(ssaSink3) | SSA.cs:60:15:60:22 | access to local variable ssaSink3 |
| SSA.cs:59:23:59:30 | [post] access to local variable ssaSink3 | SSA.cs:59:23:59:30 | SSA def(ssaSink3) |
| SSA.cs:59:23:59:30 | access to local variable ssaSink3 | SSA.cs:59:23:59:30 | SSA def(ssaSink3) |
| SSA.cs:63:23:63:30 | SSA def(nonSink0) | SSA.cs:64:15:64:22 | access to local variable nonSink0 |
| SSA.cs:63:23:63:30 | [post] access to local variable nonSink0 | SSA.cs:63:23:63:30 | SSA def(nonSink0) |
| SSA.cs:63:23:63:30 | access to local variable nonSink0 | SSA.cs:63:23:63:30 | SSA def(nonSink0) |
| SSA.cs:67:9:67:12 | [post] this access | SSA.cs:68:23:68:26 | this access |
| SSA.cs:67:9:67:12 | this access | SSA.cs:68:23:68:26 | this access |
@@ -520,6 +528,7 @@
| SSA.cs:68:23:68:26 | this access | SSA.cs:69:15:69:18 | this access |
| SSA.cs:68:23:68:28 | SSA def(this.S) | SSA.cs:69:15:69:20 | access to field S |
| SSA.cs:68:23:68:28 | SSA qualifier def(this.S.SsaFieldSink0) | SSA.cs:69:15:69:34 | access to field SsaFieldSink0 |
| SSA.cs:68:23:68:28 | [post] access to field S | SSA.cs:68:23:68:28 | SSA def(this.S) |
| SSA.cs:68:23:68:28 | access to field S | SSA.cs:68:23:68:28 | SSA def(this.S) |
| SSA.cs:69:15:69:18 | [post] this access | SSA.cs:72:9:72:12 | this access |
| SSA.cs:69:15:69:18 | this access | SSA.cs:72:9:72:12 | this access |
@@ -535,6 +544,7 @@
| SSA.cs:73:23:73:26 | this access | SSA.cs:74:15:74:18 | this access |
| SSA.cs:73:23:73:28 | SSA def(this.S) | SSA.cs:74:15:74:20 | access to field S |
| SSA.cs:73:23:73:28 | SSA qualifier def(this.S.SsaFieldNonSink0) | SSA.cs:74:15:74:37 | access to field SsaFieldNonSink0 |
| SSA.cs:73:23:73:28 | [post] access to field S | SSA.cs:73:23:73:28 | SSA def(this.S) |
| SSA.cs:73:23:73:28 | access to field S | SSA.cs:73:23:73:28 | SSA def(this.S) |
| SSA.cs:74:15:74:18 | [post] this access | SSA.cs:80:9:80:12 | this access |
| SSA.cs:74:15:74:18 | this access | SSA.cs:80:9:80:12 | this access |
@@ -584,10 +594,13 @@
| SSA.cs:91:24:91:31 | access to local variable ssaSink0 | SSA.cs:117:36:117:43 | access to local variable ssaSink0 |
| SSA.cs:92:17:92:26 | [post] access to parameter nonTainted | SSA.cs:102:13:102:22 | access to parameter nonTainted |
| SSA.cs:92:17:92:26 | access to parameter nonTainted | SSA.cs:102:13:102:22 | access to parameter nonTainted |
| SSA.cs:93:21:93:28 | [post] access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:93:21:93:28 | access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:95:21:95:28 | [post] access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:95:21:95:28 | access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:97:9:97:32 | SSA phi(ssaSink4) | SSA.cs:97:23:97:30 | access to local variable ssaSink4 |
| SSA.cs:97:23:97:30 | SSA def(ssaSink4) | SSA.cs:98:15:98:22 | access to local variable ssaSink4 |
| SSA.cs:97:23:97:30 | [post] access to local variable ssaSink4 | SSA.cs:97:23:97:30 | SSA def(ssaSink4) |
| SSA.cs:97:23:97:30 | access to local variable ssaSink4 | SSA.cs:97:23:97:30 | SSA def(ssaSink4) |
| SSA.cs:101:16:101:28 | SSA def(nonSink3) | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:101:27:101:28 | "" | SSA.cs:101:16:101:28 | SSA def(nonSink3) |
@@ -601,10 +614,13 @@
| SSA.cs:104:24:104:31 | access to local variable nonSink0 | SSA.cs:130:39:130:46 | access to local variable nonSink0 |
| SSA.cs:105:17:105:26 | [post] access to parameter nonTainted | SSA.cs:115:13:115:22 | access to parameter nonTainted |
| SSA.cs:105:17:105:26 | access to parameter nonTainted | SSA.cs:115:13:115:22 | access to parameter nonTainted |
| SSA.cs:106:21:106:28 | [post] access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:106:21:106:28 | access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:108:21:108:28 | [post] access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:108:21:108:28 | access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:110:9:110:32 | SSA phi(nonSink3) | SSA.cs:110:23:110:30 | access to local variable nonSink3 |
| SSA.cs:110:23:110:30 | SSA def(nonSink3) | SSA.cs:111:15:111:22 | access to local variable nonSink3 |
| SSA.cs:110:23:110:30 | [post] access to local variable nonSink3 | SSA.cs:110:23:110:30 | SSA def(nonSink3) |
| SSA.cs:110:23:110:30 | access to local variable nonSink3 | SSA.cs:110:23:110:30 | SSA def(nonSink3) |
| SSA.cs:114:9:114:12 | [post] this access | SSA.cs:117:13:117:16 | this access |
| SSA.cs:114:9:114:12 | [post] this access | SSA.cs:123:23:123:26 | this access |
@@ -637,17 +653,20 @@
| SSA.cs:119:21:119:24 | this access | SSA.cs:123:23:123:26 | this access |
| SSA.cs:119:21:119:26 | [post] access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:119:21:119:26 | access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:119:21:119:40 | [post] access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:119:21:119:40 | access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:121:21:121:24 | [post] this access | SSA.cs:123:23:123:26 | this access |
| SSA.cs:121:21:121:24 | this access | SSA.cs:123:23:123:26 | this access |
| SSA.cs:121:21:121:26 | [post] access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:121:21:121:26 | access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:121:21:121:40 | [post] access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:121:21:121:40 | access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) | SSA.cs:123:23:123:28 | SSA qualifier def(this.S.SsaFieldSink1) |
| SSA.cs:123:23:123:26 | [post] this access | SSA.cs:124:15:124:18 | this access |
| SSA.cs:123:23:123:26 | this access | SSA.cs:124:15:124:18 | this access |
| SSA.cs:123:23:123:28 | SSA def(this.S) | SSA.cs:124:15:124:20 | access to field S |
| SSA.cs:123:23:123:28 | SSA qualifier def(this.S.SsaFieldSink1) | SSA.cs:124:15:124:34 | access to field SsaFieldSink1 |
| SSA.cs:123:23:123:28 | [post] access to field S | SSA.cs:123:23:123:28 | SSA def(this.S) |
| SSA.cs:123:23:123:28 | access to field S | SSA.cs:123:23:123:28 | SSA def(this.S) |
| SSA.cs:124:15:124:18 | [post] this access | SSA.cs:127:9:127:12 | this access |
| SSA.cs:124:15:124:18 | this access | SSA.cs:127:9:127:12 | this access |
@@ -680,17 +699,20 @@
| SSA.cs:132:21:132:24 | this access | SSA.cs:136:23:136:26 | this access |
| SSA.cs:132:21:132:26 | [post] access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:132:21:132:26 | access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:132:21:132:43 | [post] access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:132:21:132:43 | access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:134:21:134:24 | [post] this access | SSA.cs:136:23:136:26 | this access |
| SSA.cs:134:21:134:24 | this access | SSA.cs:136:23:136:26 | this access |
| SSA.cs:134:21:134:26 | [post] access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:134:21:134:26 | access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:134:21:134:43 | [post] access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:134:21:134:43 | access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) | SSA.cs:136:23:136:28 | SSA qualifier def(this.S.SsaFieldNonSink0) |
| SSA.cs:136:23:136:26 | [post] this access | SSA.cs:137:15:137:18 | this access |
| SSA.cs:136:23:136:26 | this access | SSA.cs:137:15:137:18 | this access |
| SSA.cs:136:23:136:28 | SSA def(this.S) | SSA.cs:137:15:137:20 | access to field S |
| SSA.cs:136:23:136:28 | SSA qualifier def(this.S.SsaFieldNonSink0) | SSA.cs:137:15:137:37 | access to field SsaFieldNonSink0 |
| SSA.cs:136:23:136:28 | [post] access to field S | SSA.cs:136:23:136:28 | SSA def(this.S) |
| SSA.cs:136:23:136:28 | access to field S | SSA.cs:136:23:136:28 | SSA def(this.S) |
| SSA.cs:144:34:144:34 | t | SSA.cs:146:13:146:13 | access to parameter t |
| SSA.cs:146:13:146:13 | access to parameter t | SSA.cs:146:13:146:13 | (...) ... |
@@ -718,6 +740,7 @@
| SSA.cs:176:21:176:28 | [post] access to local variable ssaSink5 | SSA.cs:177:21:177:28 | access to local variable ssaSink5 |
| SSA.cs:176:21:176:28 | access to local variable ssaSink5 | SSA.cs:177:21:177:28 | access to local variable ssaSink5 |
| SSA.cs:177:21:177:28 | [post] access to local variable ssaSink5 | SSA.cs:176:21:176:28 | access to local variable ssaSink5 |
| SSA.cs:177:21:177:28 | [post] access to local variable ssaSink5 | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) |
| SSA.cs:177:21:177:28 | access to local variable ssaSink5 | SSA.cs:176:21:176:28 | access to local variable ssaSink5 |
| SSA.cs:177:21:177:28 | access to local variable ssaSink5 | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) |
| SSA.cs:180:9:180:24 | SSA phi(ssaSink5) | SSA.cs:180:15:180:22 | access to local variable ssaSink5 |

View File

@@ -73,6 +73,8 @@
| LocalDataFlow.cs:84:31:84:35 | [b (line 48): false] access to local variable sink6 | LocalDataFlow.cs:84:21:84:35 | [b (line 48): false] ... ? ... : ... |
| LocalDataFlow.cs:85:15:85:19 | [b (line 48): false] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:85:15:85:19 | [b (line 48): true] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:85:15:85:19 | [post] [b (line 48): false] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:85:15:85:19 | [post] [b (line 48): true] access to local variable sink7 | LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) |
| LocalDataFlow.cs:88:9:88:36 | SSA def(nonSink0) | LocalDataFlow.cs:89:15:89:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:88:20:88:36 | ... ? ... : ... | LocalDataFlow.cs:88:9:88:36 | SSA def(nonSink0) |
| LocalDataFlow.cs:88:20:88:36 | SSA phi(sink7) | LocalDataFlow.cs:92:29:92:33 | access to local variable sink7 |
@@ -598,7 +600,9 @@
| SSA.cs:38:17:38:26 | [post] access to parameter nonTainted | SSA.cs:47:13:47:22 | access to parameter nonTainted |
| SSA.cs:38:17:38:26 | access to parameter nonTainted | SSA.cs:47:13:47:22 | access to parameter nonTainted |
| SSA.cs:38:17:38:33 | access to property Length | SSA.cs:38:17:38:37 | ... > ... |
| SSA.cs:39:21:39:28 | [post] access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:39:21:39:28 | access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:41:21:41:28 | [post] access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:41:21:41:28 | access to local variable ssaSink2 | SSA.cs:43:9:43:24 | SSA phi(ssaSink2) |
| SSA.cs:43:9:43:24 | SSA phi(ssaSink2) | SSA.cs:43:15:43:22 | access to local variable ssaSink2 |
| SSA.cs:46:16:46:28 | SSA def(nonSink2) | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
@@ -615,15 +619,19 @@
| SSA.cs:50:17:50:26 | [post] access to parameter nonTainted | SSA.cs:89:13:89:22 | access to parameter nonTainted |
| SSA.cs:50:17:50:26 | access to parameter nonTainted | SSA.cs:89:13:89:22 | access to parameter nonTainted |
| SSA.cs:50:17:50:33 | access to property Length | SSA.cs:50:17:50:37 | ... > ... |
| SSA.cs:51:21:51:28 | [post] access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:51:21:51:28 | access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:53:21:53:28 | [post] access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:53:21:53:28 | access to local variable nonSink2 | SSA.cs:55:9:55:24 | SSA phi(nonSink2) |
| SSA.cs:55:9:55:24 | SSA phi(nonSink2) | SSA.cs:55:15:55:22 | access to local variable nonSink2 |
| SSA.cs:58:16:58:33 | SSA def(ssaSink3) | SSA.cs:59:23:59:30 | access to local variable ssaSink3 |
| SSA.cs:58:27:58:33 | access to parameter tainted | SSA.cs:58:16:58:33 | SSA def(ssaSink3) |
| SSA.cs:58:27:58:33 | access to parameter tainted | SSA.cs:67:32:67:38 | access to parameter tainted |
| SSA.cs:59:23:59:30 | SSA def(ssaSink3) | SSA.cs:60:15:60:22 | access to local variable ssaSink3 |
| SSA.cs:59:23:59:30 | [post] access to local variable ssaSink3 | SSA.cs:59:23:59:30 | SSA def(ssaSink3) |
| SSA.cs:59:23:59:30 | access to local variable ssaSink3 | SSA.cs:59:23:59:30 | SSA def(ssaSink3) |
| SSA.cs:63:23:63:30 | SSA def(nonSink0) | SSA.cs:64:15:64:22 | access to local variable nonSink0 |
| SSA.cs:63:23:63:30 | [post] access to local variable nonSink0 | SSA.cs:63:23:63:30 | SSA def(nonSink0) |
| SSA.cs:63:23:63:30 | access to local variable nonSink0 | SSA.cs:63:23:63:30 | SSA def(nonSink0) |
| SSA.cs:67:9:67:12 | [post] this access | SSA.cs:68:23:68:26 | this access |
| SSA.cs:67:9:67:12 | this access | SSA.cs:68:23:68:26 | this access |
@@ -636,6 +644,7 @@
| SSA.cs:68:23:68:26 | this access | SSA.cs:69:15:69:18 | this access |
| SSA.cs:68:23:68:28 | SSA def(this.S) | SSA.cs:69:15:69:20 | access to field S |
| SSA.cs:68:23:68:28 | SSA qualifier def(this.S.SsaFieldSink0) | SSA.cs:69:15:69:34 | access to field SsaFieldSink0 |
| SSA.cs:68:23:68:28 | [post] access to field S | SSA.cs:68:23:68:28 | SSA def(this.S) |
| SSA.cs:68:23:68:28 | access to field S | SSA.cs:68:23:68:28 | SSA def(this.S) |
| SSA.cs:69:15:69:18 | [post] this access | SSA.cs:72:9:72:12 | this access |
| SSA.cs:69:15:69:18 | this access | SSA.cs:72:9:72:12 | this access |
@@ -651,6 +660,7 @@
| SSA.cs:73:23:73:26 | this access | SSA.cs:74:15:74:18 | this access |
| SSA.cs:73:23:73:28 | SSA def(this.S) | SSA.cs:74:15:74:20 | access to field S |
| SSA.cs:73:23:73:28 | SSA qualifier def(this.S.SsaFieldNonSink0) | SSA.cs:74:15:74:37 | access to field SsaFieldNonSink0 |
| SSA.cs:73:23:73:28 | [post] access to field S | SSA.cs:73:23:73:28 | SSA def(this.S) |
| SSA.cs:73:23:73:28 | access to field S | SSA.cs:73:23:73:28 | SSA def(this.S) |
| SSA.cs:74:15:74:18 | [post] this access | SSA.cs:80:9:80:12 | this access |
| SSA.cs:74:15:74:18 | this access | SSA.cs:80:9:80:12 | this access |
@@ -702,10 +712,13 @@
| SSA.cs:92:17:92:26 | [post] access to parameter nonTainted | SSA.cs:102:13:102:22 | access to parameter nonTainted |
| SSA.cs:92:17:92:26 | access to parameter nonTainted | SSA.cs:102:13:102:22 | access to parameter nonTainted |
| SSA.cs:92:17:92:33 | access to property Length | SSA.cs:92:17:92:37 | ... > ... |
| SSA.cs:93:21:93:28 | [post] access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:93:21:93:28 | access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:95:21:95:28 | [post] access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:95:21:95:28 | access to local variable ssaSink4 | SSA.cs:97:9:97:32 | SSA phi(ssaSink4) |
| SSA.cs:97:9:97:32 | SSA phi(ssaSink4) | SSA.cs:97:23:97:30 | access to local variable ssaSink4 |
| SSA.cs:97:23:97:30 | SSA def(ssaSink4) | SSA.cs:98:15:98:22 | access to local variable ssaSink4 |
| SSA.cs:97:23:97:30 | [post] access to local variable ssaSink4 | SSA.cs:97:23:97:30 | SSA def(ssaSink4) |
| SSA.cs:97:23:97:30 | access to local variable ssaSink4 | SSA.cs:97:23:97:30 | SSA def(ssaSink4) |
| SSA.cs:101:16:101:28 | SSA def(nonSink3) | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:101:27:101:28 | "" | SSA.cs:101:16:101:28 | SSA def(nonSink3) |
@@ -721,10 +734,13 @@
| SSA.cs:105:17:105:26 | [post] access to parameter nonTainted | SSA.cs:115:13:115:22 | access to parameter nonTainted |
| SSA.cs:105:17:105:26 | access to parameter nonTainted | SSA.cs:115:13:115:22 | access to parameter nonTainted |
| SSA.cs:105:17:105:33 | access to property Length | SSA.cs:105:17:105:37 | ... > ... |
| SSA.cs:106:21:106:28 | [post] access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:106:21:106:28 | access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:108:21:108:28 | [post] access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:108:21:108:28 | access to local variable nonSink3 | SSA.cs:110:9:110:32 | SSA phi(nonSink3) |
| SSA.cs:110:9:110:32 | SSA phi(nonSink3) | SSA.cs:110:23:110:30 | access to local variable nonSink3 |
| SSA.cs:110:23:110:30 | SSA def(nonSink3) | SSA.cs:111:15:111:22 | access to local variable nonSink3 |
| SSA.cs:110:23:110:30 | [post] access to local variable nonSink3 | SSA.cs:110:23:110:30 | SSA def(nonSink3) |
| SSA.cs:110:23:110:30 | access to local variable nonSink3 | SSA.cs:110:23:110:30 | SSA def(nonSink3) |
| SSA.cs:114:9:114:12 | [post] this access | SSA.cs:117:13:117:16 | this access |
| SSA.cs:114:9:114:12 | [post] this access | SSA.cs:123:23:123:26 | this access |
@@ -759,17 +775,20 @@
| SSA.cs:119:21:119:24 | this access | SSA.cs:123:23:123:26 | this access |
| SSA.cs:119:21:119:26 | [post] access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:119:21:119:26 | access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:119:21:119:40 | [post] access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:119:21:119:40 | access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:121:21:121:24 | [post] this access | SSA.cs:123:23:123:26 | this access |
| SSA.cs:121:21:121:24 | this access | SSA.cs:123:23:123:26 | this access |
| SSA.cs:121:21:121:26 | [post] access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:121:21:121:26 | access to field S | SSA.cs:123:23:123:28 | access to field S |
| SSA.cs:121:21:121:40 | [post] access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:121:21:121:40 | access to field SsaFieldSink1 | SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) |
| SSA.cs:123:9:123:30 | SSA phi(this.S.SsaFieldSink1) | SSA.cs:123:23:123:28 | SSA qualifier def(this.S.SsaFieldSink1) |
| SSA.cs:123:23:123:26 | [post] this access | SSA.cs:124:15:124:18 | this access |
| SSA.cs:123:23:123:26 | this access | SSA.cs:124:15:124:18 | this access |
| SSA.cs:123:23:123:28 | SSA def(this.S) | SSA.cs:124:15:124:20 | access to field S |
| SSA.cs:123:23:123:28 | SSA qualifier def(this.S.SsaFieldSink1) | SSA.cs:124:15:124:34 | access to field SsaFieldSink1 |
| SSA.cs:123:23:123:28 | [post] access to field S | SSA.cs:123:23:123:28 | SSA def(this.S) |
| SSA.cs:123:23:123:28 | access to field S | SSA.cs:123:23:123:28 | SSA def(this.S) |
| SSA.cs:124:15:124:18 | [post] this access | SSA.cs:127:9:127:12 | this access |
| SSA.cs:124:15:124:18 | this access | SSA.cs:127:9:127:12 | this access |
@@ -804,17 +823,20 @@
| SSA.cs:132:21:132:24 | this access | SSA.cs:136:23:136:26 | this access |
| SSA.cs:132:21:132:26 | [post] access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:132:21:132:26 | access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:132:21:132:43 | [post] access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:132:21:132:43 | access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:134:21:134:24 | [post] this access | SSA.cs:136:23:136:26 | this access |
| SSA.cs:134:21:134:24 | this access | SSA.cs:136:23:136:26 | this access |
| SSA.cs:134:21:134:26 | [post] access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:134:21:134:26 | access to field S | SSA.cs:136:23:136:28 | access to field S |
| SSA.cs:134:21:134:43 | [post] access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:134:21:134:43 | access to field SsaFieldNonSink0 | SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) |
| SSA.cs:136:9:136:30 | SSA phi(this.S.SsaFieldNonSink0) | SSA.cs:136:23:136:28 | SSA qualifier def(this.S.SsaFieldNonSink0) |
| SSA.cs:136:23:136:26 | [post] this access | SSA.cs:137:15:137:18 | this access |
| SSA.cs:136:23:136:26 | this access | SSA.cs:137:15:137:18 | this access |
| SSA.cs:136:23:136:28 | SSA def(this.S) | SSA.cs:137:15:137:20 | access to field S |
| SSA.cs:136:23:136:28 | SSA qualifier def(this.S.SsaFieldNonSink0) | SSA.cs:137:15:137:37 | access to field SsaFieldNonSink0 |
| SSA.cs:136:23:136:28 | [post] access to field S | SSA.cs:136:23:136:28 | SSA def(this.S) |
| SSA.cs:136:23:136:28 | access to field S | SSA.cs:136:23:136:28 | SSA def(this.S) |
| SSA.cs:144:34:144:34 | t | SSA.cs:146:13:146:13 | access to parameter t |
| SSA.cs:146:13:146:13 | (...) ... | SSA.cs:146:13:146:21 | ... == ... |
@@ -846,6 +868,7 @@
| SSA.cs:176:21:176:28 | [post] access to local variable ssaSink5 | SSA.cs:177:21:177:28 | access to local variable ssaSink5 |
| SSA.cs:176:21:176:28 | access to local variable ssaSink5 | SSA.cs:177:21:177:28 | access to local variable ssaSink5 |
| SSA.cs:177:21:177:28 | [post] access to local variable ssaSink5 | SSA.cs:176:21:176:28 | access to local variable ssaSink5 |
| SSA.cs:177:21:177:28 | [post] access to local variable ssaSink5 | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) |
| SSA.cs:177:21:177:28 | access to local variable ssaSink5 | SSA.cs:176:21:176:28 | access to local variable ssaSink5 |
| SSA.cs:177:21:177:28 | access to local variable ssaSink5 | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) |
| SSA.cs:180:9:180:24 | SSA phi(ssaSink5) | SSA.cs:180:15:180:22 | access to local variable ssaSink5 |

View File

@@ -1,7 +1,7 @@
name: codeql-csharp-tests
groups: [csharp, test]
dependencies:
codeql/csharp-all: "*"
codeql/csharp-queries: "*"
codeql/csharp-all: ${workspace}
codeql/csharp-queries: ${workspace}
extractor: csharp
tests: .

View File

@@ -819,13 +819,15 @@ A class definition has the following syntax:
::
class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}"
class ::= qldoc? annotations "class" classname ("extends" type ("," type)*)? ("instanceof" type ("," type)*)? "{" member* "}"
The identifier following the ``class`` keyword is the name of the class.
The types specified after the ``extends`` keyword are the *base types* of the class.
A class domain type is said to *inherit* from the base types of the associated class type, a character type is said to *inherit* from its associated class domain type and a class type is said to *inherit* from its associated character type. In addition, inheritance is transitive: If a type ``A`` inherits from a type ``B``, and ``B`` inherits from a type ``C``, then ``A`` inherits from ``C``.
The types specified after the ``instanceof`` keyword are the *instanceof types* of the class.
A class type is said to *inherit* from the base types. In addition, inheritance is transitive: If a type ``A`` inherits from a type ``B``, and ``B`` inherits from a type ``C``, then ``A`` inherits from ``C``.
A class adds a mapping from the class name to the class declaration to the current module's declared type environment.
@@ -833,6 +835,20 @@ A valid class can be annotated with ``abstract``, ``final``, ``library``, and ``
A valid class may not inherit from a final class, from itself, or from more than one primitive type.
A valid class must have at least one base type or instanceof type.
Class dependencies
~~~~~~~~~~~~~~~~~~
The program is invalid if there is a cycle of class dependencies.
The following are class dependencies:
- ``C`` depends on ``C.C``
- ``C.C`` depends on ``C.extends``
- If ``C`` is abstract then it depends on all classes ``D`` such that ``C`` is a base type of ``D``.
- ``C.extends`` depends on ``D.D`` for each base type ``D`` of ``C``.
- ``C.extends`` depends on ``D`` for each instanceof type ``D`` of ``C``.
Class environments
~~~~~~~~~~~~~~~~~~
@@ -848,7 +864,9 @@ For each of member predicates and fields a class *inherits* and *declares*, and
The program is invalid if any of these environments is not definite.
For each of member predicates and fields a domain type *exports* an environment. This is the union of the exported ``X`` environments of types the class inherits from, excluding any elements that are ``overridden`` by another element.
For each of member predicates and fields a domain type *exports* an environment. We say the *exported X extends environment* is the union of the exported ``X`` environments of types the class inherits from, excluding any elements that are ``overridden`` by another element.
We say the *exported X instanceof environement* is the union of the exported ``X`` environments of types that a instanceof type inherits from, excluding any elements that are ``overridden`` by another element.
The *exported X environment* of the domain type is the union of the exported ``X`` extends environment and the exported ``X`` instanceof environement.
Members
~~~~~~~
@@ -1090,11 +1108,7 @@ A super expression has the following syntax:
super_expr ::= "super" | type "." "super"
For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the type of ``this`` in the typing environment.
A super expression may only occur in a QL program as the receiver expression for a predicate call.
If a super expression includes a ``type``, then that type must be a class that the enclosing class inherits from.
For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the domain type of the type of ``this`` in the typing environment.
The value of a super expression is the same as the value of ``this`` in the named tuple.
@@ -1147,13 +1161,6 @@ A valid call with results *resolves* to a set of predicates. The ways a call can
- If the call has no receiver and the predicate name is a selection identifier, then the qualifier is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier is then resolved in the exported predicate environment of the qualifier module.
- If the call has a super expression as the receiver, then it resolves to a member predicate in a class that the enclosing class inherits from:
- If the super expression is unqualified and there is a single class that the current class inherits from, then the super-class is that class.
- If the super expression is unqualified and there are multiple classes that the current class inherits from, then the super-class is the domain type.
- Otherwise, the super-class is the class named by the qualifier of the super expression.
The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class.
- If the type of the receiver is the same as the enclosing class, the predicate is resolved by looking up its name and arity in the visible predicate environment of the class.
- If the type of the receiver is not the same as the enclosing class, the predicate is resolved by looking up its name and arity in the exported predicate environment of the class or domain type.
@@ -1177,11 +1184,20 @@ If the resolved predicate is built in, then the call may not include a closure.
If the call includes a closure, then all declared predicate arguments, the enclosing type of the declaration (if it exists), and the result type of the declaration (if it exists) must be compatible. If one of those types is a subtype of ``int``, then all the other arguments must be a subtype of ``int``.
A call to a member predicate may be a *direct* call:
- If the receiver is not a super expression it is not direct.
- If the receiver is ``A.super`` and ``A`` is an instanceof type and not a base type then it is not direct.
- If the receiver is ``A.super`` and ``A`` is a base type type and not an instanceof type then it is direct.
- If the receiver is ``A.super`` and ``A`` is a base type and an instanceof type then the call is not valid.
- If the receiver is ``super`` and the member predicate is in the exported member predicate environment of an instanceof type and not in the exported member predicate environment of a base type then it isn't direct.
- If the receiver is ``super`` and the member predicate is in the exported member predicate environment of a base type and not in the exported member predicate environment of an instanceof type then it is direct.
- If the receiver is ``super`` and the member predicate is in the exported member predicate environment of a base type and in the exported member predicate environment of an instanceof type then the call is not valid.
If the call resolves to a member predicate, then the *receiver values* are as follows. If the call has a receiver, then the receiver values are the values of that receiver. If the call does not have a receiver, then the single receiver value is the value of ``this`` in the contextual named tuple.
The *tuple prefixes* of a call with results include one value from each of the argument expressions' values, in the same order as the order of the arguments. If the call resolves to a non-member predicate, then those values are exactly the tuple prefixes of the call. If the call instead resolves to a member predicate, then the tuple prefixes additionally include a receiver value, ordered before the argument values.
The *matching tuples* of a call with results are all ordered tuples that are one of the tuple prefixes followed by any value of the same type as the call. If the call has no closure, then all matching tuples must additionally satisfy the resolved predicate of the call, unless the receiver is a super expression, in which case they must *directly* satisfy the resolved predicate of the call. If the call has a ``*`` or ``+`` closure, then the matching tuples must satisfy or directly satisfy the associated closure of the resolved predicate.
The *matching tuples* of a call with results are all ordered tuples that are one of the tuple prefixes followed by any value of the same type as the call. If the call has no closure, then all matching tuples must additionally satisfy the resolved predicate of the call, unless the call is direct in which case they must *directly* satisfy the resolved predicate of the call. If the call has a ``*`` or ``+`` closure, then the matching tuples must satisfy or directly satisfy the associated closure of the resolved predicate.
The values of a call with results are the final elements of each of the call's matching tuples.
@@ -1534,13 +1550,15 @@ The identifier is called the *predicate name* of the call.
A call must resolve to a predicate, using the same definition of resolve as for calls with results (see "`Calls with results <#calls-with-results>`__").
A call may be direct using the same definition of direct as for calls with results (see "`Calls with results <#calls-with-results>`__").
The resolved predicate must not have a result type.
If the resolved predicate is a built-in member predicate of a primitive type, then the call may not include a closure. If the call does have a closure, then the call must resolve to a predicate with relational arity of 2.
The *candidate tuples* of a call are the ordered tuples formed by selecting a value from each of the arguments of the call.
If the call has no closure, then it matches whenever one of the candidate tuples satisfies the resolved predicate of the call, unless the call has a super expression as a receiver, in which case the candidate tuple must *directly* satisfy the resolved predicate. If the call has ``*`` or ``+`` closure, then the call matches whenever one of the candidate tuples satisfies or directly satisfies the associated closure of the resolved predicate.
If the call has no closure, then it matches whenever one of the candidate tuples satisfies the resolved predicate of the call, unless the call is direct, in which case the candidate tuple must *directly* satisfy the resolved predicate. If the call has ``*`` or ``+`` closure, then the call matches whenever one of the candidate tuples satisfies or directly satisfies the associated closure of the resolved predicate.
Disambiguation of formulas
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1926,10 +1944,12 @@ Predicates, and types can *depend* and *strictly depend* on each other. Such dep
- A predicate containing a predicate call depends on the predicate to which the call resolves. If the call has negative or zero polarity then the dependency is strict.
- A predicate containing a predicate call, which resolves to a member predicate and does not have a ``super`` expression as a qualifier, depends on the dispatch dependencies of the root definitions of the target of the call. If the call has negative or zero polarity then the dependencies are strict. The predicate strictly depends on the strict dispatch dependencies of the root definitions.
- A predicate containing a predicate call, which resolves to a member predicate, where the call is not direct, depends on the dispatch dependencies of the root definitions of the target of the call. If the call has negative or zero polarity then the dependencies are strict. The predicate strictly depends on the strict dispatch dependencies of the root definitions.
- For each class ``C`` in the program, for each base class ``B`` of ``C``, ``C.extends`` depends on ``B.B``.
- For each class ``C`` in the program, for each instanceof type ``B`` of ``C``, ``C.extends`` depends on ``B``.
- For each class ``C`` in the program, for each base type ``B`` of ``C`` that is not a class type, ``C.extends`` depends on ``B``.
- For each class ``C`` in the program, ``C.class`` depends on ``C.C``.
@@ -1976,6 +1996,7 @@ Each layer of the stratification is *populated* in order. To populate a layer, e
- To populate the type ``C.extends`` for a class ``C``, identify each named tuple that has the following properties:
- The value of ``this`` is in all non-class base types of ``C``.
- The value of ``this`` is in all instanceof types of ``C``.
- The keys of the tuple are ``this`` and the union of the public fields from each base type.
- For each class base type ``B`` of ``C`` there is a named tuple with variables from the public fields of ``B`` and ``this`` that the given tuple and some tuple in ``B.B`` both extend.
@@ -2060,7 +2081,7 @@ The complete grammar for QL is as follows:
| "{" formula "}"
| "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")"
class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}"
class ::= qldoc? annotations "class" classname ("extends" type ("," type)*)? ("instanceof" type ("," type)*)? "{" member* "}"
member ::= character | predicate | field

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