Compare commits

..

372 Commits

Author SHA1 Message Date
github-actions[bot]
5babe3d0a6 use ATM model from training run classification_1659313637_335f5d4e_foo_3 2022-09-14 12:22:50 +00:00
Ian Lynagh
6d5d78e975 Merge pull request #10275 from igfoo/igfoo/TypeResults
Kotlin: Fix the type of TypeResultGeneric.cast
2022-09-02 14:34:22 +01:00
Ian Lynagh
c339a2d4a7 Merge pull request #10273 from igfoo/igfoo/extractRawMethodAccess
Kotlin: Remove cast from extractRawMethodAccess
2022-09-02 13:26:33 +01:00
Ian Lynagh
ed04bec34e Merge pull request #10274 from igfoo/igfoo/extractCall
Kotlin: Remove a cast in array iterator call extraction
2022-09-02 13:26:10 +01:00
Ian Lynagh
3195404b63 Merge pull request #10272 from igfoo/igfoo/getDeclaringTypeArguments
Kotlin: Remove some casts from getDeclaringTypeArguments
2022-09-02 13:13:40 +01:00
Ian Lynagh
3646d1d294 Kotlin: Fix the type of TypeResultGeneric.cast 2022-09-02 12:39:46 +01:00
Ian Lynagh
a56876533f Kotlin: Remove a cast in array iterator call extraction 2022-09-02 12:25:14 +01:00
Ian Lynagh
db1661fb13 Kotlin: Remove cast from extractRawMethodAccess
I'm not entirely happy with this, but it at least meets the goal of
removing the cast.
2022-09-02 12:14:09 +01:00
Ian Lynagh
3eab35d78b Kotlin: Small simplification 2022-09-02 12:04:21 +01:00
Ian Lynagh
07b3b15528 Merge pull request #10221 from tamasvajk/kotlin-internal
Kotlin: Change `Modifiable::isPublic` to not cover Kotlin `internal` members
2022-09-02 11:51:56 +01:00
Ian Lynagh
6a4b748958 Kotlin: Remove some casts from getDeclaringTypeArguments 2022-09-02 11:50:00 +01:00
Ian Lynagh
4f7eb7be83 Merge pull request #10262 from igfoo/igfoo/useArrayType
Kotlin: Avoid unsafe casts in useArrayType
2022-09-02 10:25:34 +01:00
Ian Lynagh
b05d8a61ba Merge pull request #10263 from igfoo/igfoo/useSimpleType3
Kotlin: Remove some casts in useSimpleType
2022-09-02 10:25:23 +01:00
Tom Hvitved
2c584d8f35 Merge pull request #10235 from hvitved/csharp/remove-legacy-tracer
C#: Remove legacy tracer support
2022-09-02 09:25:10 +02:00
Tamas Vajk
bea0ce9ff9 Fix review findings 2022-09-02 09:20:20 +02:00
Erik Krogh Kristensen
6cee635cb5 Merge pull request #10180 from erik-krogh/fixTags
Add missing security tags
2022-09-02 08:04:57 +02:00
Nora Dimitrijević
7584434b80 Merge pull request #10163 from d10c/missing-check-scanf-squashed
C++: New Query: missing return-value check for scanf-like functions
2022-09-01 23:43:21 +02:00
Ian Lynagh
9d3bc47a4d Kotlin: Remove some casts in useSimpleType 2022-09-01 17:36:31 +01:00
Ian Lynagh
ddb7bb11fd Kotlin: Avoid unsafe casts in useArrayType 2022-09-01 17:15:15 +01:00
Mathias Vorreiter Pedersen
2223bc3d1f Merge pull request #10261 from MathiasVP/fix-join-in-sign-analysis
C++: Fix join in sign analysis
2022-09-01 16:49:05 +01:00
Ian Lynagh
ae9ba80c40 Merge pull request #10242 from igfoo/igfoo/kotlinFunctionToJavaEquivalent
Kotlin: Refactor kotlinFunctionToJavaEquivalent
2022-09-01 16:23:08 +01:00
Tom Hvitved
3c3390728a Merge pull request #10245 from hvitved/ruby/simplify-track-instance
Ruby: Exclude top-level `self` accesses from `trackModule`
2022-09-01 16:50:14 +02:00
Ian Lynagh
710ba3cb14 Merge pull request #10257 from igfoo/igfoo/hasModifier
Java: Correct hasModifier documentation
2022-09-01 15:49:06 +01:00
Edoardo Pirovano
8f332714f4 Merge pull request #10260 from github/edoardo/3.7-mergeback
Merge `rc/3.7` into `main`
2022-09-01 15:44:17 +01:00
Mathias Vorreiter Pedersen
a65e585db1 C++: 'nomagic' on 'binaryExprOperands'. 2022-09-01 15:34:59 +01:00
Henry Mercer
e4d22a2a5a Merge pull request #10258 from github/codeql-ci/js/ml-powered-pack-release-0.3.2
JS: Bump version numbers of ML-powered packs after 0.3.2 release
2022-09-01 13:49:16 +01:00
Tamas Vajk
e66d2dddb6 Fix review findings 2022-09-01 14:07:27 +02:00
Henry Mercer
c65ae88c6d Merge branch 'main' into codeql-ci/js/ml-powered-pack-release-0.3.2 2022-09-01 12:41:45 +01:00
github-actions[bot]
8d0ca9c772 JS: Bump version of ML-powered library and query packs to 0.3.3 2022-09-01 11:39:32 +00:00
github-actions[bot]
d577392dee JS: Bump patch version of ML-powered library and query packs 2022-09-01 11:28:25 +00:00
Tamás Vajk
6576f19873 Merge pull request #10255 from tamasvajk/kotlin-array-get-fix
Kotlin: Fix array indexer extraction
2022-09-01 13:28:18 +02:00
Mathias Vorreiter Pedersen
00c55092ee Merge pull request #10256 from geoffw0/cleartextcleanup 2022-09-01 12:15:57 +01:00
Ian Lynagh
4f63317369 Kotlin: Remove a redundant ? 2022-09-01 11:55:43 +01:00
Ian Lynagh
7ed18f1b32 Java: Correct hasModifier documentation 2022-09-01 11:52:07 +01:00
Ian Lynagh
cc1a5d82b8 Merge pull request #10243 from igfoo/igfoo/extractExpression
Kotlin: Removed a couple of casts from extractExpression
2022-09-01 11:11:58 +01:00
Ian Lynagh
70cabf188e Merge pull request #10246 from igfoo/igfoo/extractConstructorCall
Kotlin: Refactor extractConstructorCall
2022-09-01 11:11:48 +01:00
Ian Lynagh
c30f39df33 Merge pull request #10247 from igfoo/igfoo/useSimpleType2
Kotlin: Remove another cast
2022-09-01 11:11:37 +01:00
Nora Dimitrijević
f956999891 Merge branch 'main' into missing-check-scanf-squashed 2022-09-01 12:08:50 +02:00
Geoffrey White
aad77c2388 Swift: Use TypeDecl.getABaseTypeDecl(). 2022-09-01 10:42:09 +01:00
Geoffrey White
8ff0a191be Merge pull request #10254 from MathiasVP/swift-base-and-derived-on-decls
Swift: Add `getBaseTypeDecl` to `TypeDecl`
2022-09-01 10:35:29 +01:00
Tamas Vajk
a5415c9c8a Kotlin: Fix array indexer extraction 2022-09-01 11:12:14 +02:00
Tamas Vajk
afeea64078 Kotlin: Add test case for overloaded array get 2022-09-01 11:09:44 +02:00
Tom Hvitved
4d485163a6 Ruby: Exclude top-level self accesses from trackModule 2022-09-01 11:05:53 +02:00
Mathias Vorreiter Pedersen
96752f0fc4 Merge pull request #10061 from geoffw0/cleartext
Swift: Queries for CWE-311 (originally CWE-200)
2022-09-01 09:39:58 +01:00
Mathias Vorreiter Pedersen
e294b8f74a Swift: Add convenience member predicates to 'TypeDecl'. 2022-09-01 09:28:37 +01:00
Geoffrey White
d3250a7e16 Swift: Fix finding base classes. 2022-09-01 09:01:56 +01:00
Geoffrey White
92a927efa7 Swift: Remove special case (no longer required). 2022-09-01 08:53:51 +01:00
Tom Hvitved
d5200efef3 Merge pull request #10203 from hvitved/ssa/param-module
SSA: Make shared library a parameterized module
2022-09-01 09:27:05 +02:00
Anders Schack-Mulligen
efcd47f114 Merge pull request #10248 from github/workflow/coverage/update
Update CSV framework coverage reports
2022-09-01 09:17:46 +02:00
github-actions[bot]
c8441abaac Add changed framework coverage reports 2022-09-01 00:18:02 +00:00
Ian Lynagh
e4ff25099b Kotlin: Be more permissive
I think we'll end up giving a warning/error later, but that's better
than having a cast throw now.
2022-08-31 18:09:36 +01:00
Ian Lynagh
86034dc602 Kotlin: Add a type signature 2022-08-31 18:05:30 +01:00
Geoffrey White
129ed426a0 Swift: Use allowImplicitRead as a better solution replacing one of the special flow cases. 2022-08-31 17:58:18 +01:00
Geoffrey White
c0bc0d78cc Swift: Accept test changes after merging main (again). 2022-08-31 17:58:10 +01:00
Ian Lynagh
c8deb72ede Kotlin: Refactor extractConstructorCall
Avoids some casts.
2022-08-31 16:53:59 +01:00
Paolo Tranquilli
74cd532adc Merge pull request #10244 from geoffw0/swiftcleanup
Swift: Clean up the URL.init model.
2022-08-31 17:37:35 +02:00
Geoffrey White
60fad4d652 Merge remote-tracking branch 'upstream/main' into swiftcleanup 2022-08-31 16:04:39 +01:00
Nora Dimitrijević
f5a30c7bbe C++: Add correctness tag
As that seems to be appropriate for this query.
2022-08-31 16:59:57 +02:00
Nora Dimitrijević
38f185bee4 C++: Correct CWE tags in metadata 2022-08-31 16:58:05 +02:00
Tom Hvitved
18b5ab0862 C#: Remove legacy tracer support 2022-08-31 16:57:59 +02:00
Tom Hvitved
c75c489707 C#: Inject /p:MvcBuildViews=true using tracer instead of auto-builder 2022-08-31 16:57:59 +02:00
Tom Hvitved
914b9680c0 C#: Also inject /p:UseSharedCompilation=false to (x|ms)build.exe (Windows) 2022-08-31 16:57:59 +02:00
Ian Lynagh
eca28af883 Kotlin: Removed a couple of casts from extractExpression 2022-08-31 15:34:18 +01:00
Geoffrey White
be88c4f171 Swift: Clean up the URL.init model. 2022-08-31 15:25:24 +01:00
Ian Lynagh
6d00860cc1 Kotlin: Refactor kotlinFunctionToJavaEquivalent
Avoids a cast.
2022-08-31 15:03:30 +01:00
Nora Dimitrijević
0729e42536 C++: Update metadata based on cwe-scores
Though the codeql/cwe-scores update-queries.py script did not make any changes on its own,
I looked up the score of the CWEs that @geoffw0 suggested using the explain.py script.

As discussed elsewhere, this should be more of a warning than a recommendation.
2022-08-31 15:50:37 +02:00
Tamás Vajk
bf7437fd2e Merge pull request #10224 from tamasvajk/kotlin-comment-fixes
Kotlin: Fix issues in comment extraction
2022-08-31 14:22:09 +02:00
Ian Lynagh
b5f9fbe247 Merge pull request #10228 from igfoo/igfoo/useSimpleType
Kotlin: Refactor useSimpleType to avoid some casts
2022-08-31 11:32:35 +01:00
Ian Lynagh
da7d2709d9 Merge pull request #10227 from igfoo/igfoo/extractStaticTypeAccessQualifier
Kotlin: Refactor extractStaticTypeAccessQualifier
2022-08-31 11:32:26 +01:00
Ian Lynagh
49ba391923 Merge pull request #10229 from igfoo/igfoo/singleOrNullSubType
Kotlin: Implement and use singleOrNullSubType
2022-08-31 11:32:11 +01:00
Tom Hvitved
7a2d43432e C++: Adapt to parameterized SSA implementation 2022-08-31 11:56:24 +02:00
Tom Hvitved
643efb3d6b Swift: Adapt to parameterized SSA implementation 2022-08-31 11:56:24 +02:00
Asger F
99bd6f1872 Merge pull request #10234 from asgerf/js/def-nodes-for-class-members
JS: Make API graph more sparse for escaping class instance members
2022-08-31 11:51:11 +02:00
Tom Hvitved
61b67640f4 Ruby: Adapt to parameterized SSA implementation 2022-08-31 11:45:15 +02:00
Tom Hvitved
760c7beb94 SSA: Sync files 2022-08-31 11:45:15 +02:00
Tom Hvitved
2681b88035 C#: Update Pre SSA library to use parameterized module 2022-08-31 11:45:15 +02:00
Tom Hvitved
8725bf0620 C#: Update Base SSA library to use parameterized module 2022-08-31 11:45:15 +02:00
Tom Hvitved
f553001217 C#: Update CIL SSA library to use parameterized module 2022-08-31 11:45:14 +02:00
Tom Hvitved
0d81a6409d SSA: Make shared library a parameterized module 2022-08-31 11:45:14 +02:00
Mathias Vorreiter Pedersen
f846c262dc Merge pull request #10157 from MathiasVP/swift-field-flow-2
Swift: Add field flow
2022-08-31 10:42:00 +01:00
Paolo Tranquilli
1f0ca6b02a Merge pull request #10237 from github/redsun82/swift-generate-printast
Swift: add generic type parameters to AST children
2022-08-31 11:23:29 +02:00
Paolo Tranquilli
281cd79b48 Swift: add generics to ast tests 2022-08-31 11:09:35 +02:00
Michael Nebel
1cb6d78d35 Merge pull request #10170 from michaelnebel/java/models-io
Java: Update models for commons-io and add negative models.
2022-08-31 11:05:09 +02:00
Paolo Tranquilli
c0f477e5c1 Swift: reorder generic type param children in nominal types 2022-08-31 10:57:34 +02:00
Paolo Tranquilli
66e6c7bb13 Swift: make GenericTypeParamDecls children 2022-08-31 10:47:36 +02:00
Paolo Tranquilli
3ce76e6c08 Swift: preserve base order in code generation 2022-08-31 10:45:22 +02:00
Mathias Vorreiter Pedersen
9545598daf Merge pull request #10226 from github/redsun82/swift-generate-printast
Swift: add `PrintAst`
2022-08-31 09:26:46 +01:00
Tony Torralba
2ec53bf78c Merge pull request #9873 from luchua-bc/java/permissive-dot-regex
Java: CWE-625 Query to detect regex dot bypass
2022-08-31 10:24:18 +02:00
Tamas Vajk
0cbb73a47e Improve code quality 2022-08-31 09:02:35 +02:00
Paolo Tranquilli
bb845c6d7f Swift: rename printast.ql->printAst.ql 2022-08-31 08:55:40 +02:00
Paolo Tranquilli
742cf0a593 Swift: hide orphaned DeclRefExpr nodes 2022-08-31 08:35:00 +02:00
Tom Hvitved
e4853d0e71 Merge pull request #10086 from michaelnebel/csharp/cil
C#: CIL Extractor option.
2022-08-31 08:22:18 +02:00
Tom Hvitved
787234cf5c Merge pull request #10232 from github/workflow/coverage/update
Update CSV framework coverage reports
2022-08-31 08:18:50 +02:00
Paolo Tranquilli
8f09485414 Swift: enhance PrintAst testing
The `ParentChild` tests have been generalized to test all `PrintAst`
by factoring out `PrintAstNode` into a separate file.

The `child.ql` and `parent.ql` tests have been removed as they are
subsumed by `PrintAst.ql`. Also, a new `no_parent_child_loops` is
added to detect back edges to a root node (back edges to a non-root
node are already detected by `no_double_parents.ql`).
2022-08-31 06:54:30 +02:00
Paolo Tranquilli
cd632dcfee Swift: minor tweaks
Replace string singleton with a newtype-based one, and fix some doc
comment cosmetics.
2022-08-31 06:39:35 +02:00
github-actions[bot]
6c3c41e710 Add changed framework coverage reports 2022-08-31 00:21:31 +00:00
luchua-bc
e2e87980cc Move pattern check to MatchRegexConfiguration::isSink 2022-08-30 22:48:12 +00:00
Asger F
32c8688805 JS: Make API graph more sparse for escaping class instance members 2022-08-30 20:24:55 +02:00
Mathias Vorreiter Pedersen
a4209df239 Merge branch 'main' into swift-field-flow-2 2022-08-30 18:52:23 +01:00
Ian Lynagh
6f82b06bd7 Kotlin: Implement and use singleOrNullSubType
Pulls another cast out into a utility function.
2022-08-30 18:31:01 +01:00
Geoffrey White
3e4a6be53f Swift: Add missing test annotations. 2022-08-30 18:12:26 +01:00
Geoffrey White
430a8e141d Swift: Fix issues. 2022-08-30 18:04:12 +01:00
Ian Lynagh
a07be192fa Kotlin: Refactor useSimpleType to avoid some casts 2022-08-30 17:55:57 +01:00
Asger F
5ad6c05a9c Merge pull request #10205 from asgerf/mad-generics
Support type variables in MaD typings
2022-08-30 18:07:39 +02:00
Ian Lynagh
3459e5e432 Kotlin: Refactor extractStaticTypeAccessQualifier
Avoids a cast
2022-08-30 17:06:13 +01:00
Paolo Tranquilli
47b905bfaf Swift: add PrintAst 2022-08-30 18:04:55 +02:00
Paolo Tranquilli
6914c4469c Swift: accept tests after children changes 2022-08-30 17:36:39 +02:00
Paolo Tranquilli
4825e6b8ba Swift: change some children
* made `members` children of an `IterableDeclContext`
* removed `elements` from the children of `EnumCaseDecl`, as they are
  already children of the enclosing `EnumDecl`
* removed `base` from the children of `SelfApplyExpr`, as they currently
  are already descendants via `getArgument(0).getExpr()`. We should
  maybe consider either removing `base` from the schema and add it as
  a shortcut on QL, or finish up replacing all `SelfApplyExpr` instances
  with synthesized types.
2022-08-30 17:30:39 +02:00
Aditya Sharad
65095e0c5f Merge pull request #10013 from adityasharad/docs/codeql-tools-changelog-links
Docs: Add CodeQL standard packs and bundle to CodeQL tools page
2022-08-30 07:54:42 -07:00
Asger F
0d88d20b56 JS: Actually update test output this time 2022-08-30 16:44:01 +02:00
Tamas Vajk
1bc105aff6 Kotlin: adjust log messages and severities in comment extraction 2022-08-30 15:45:25 +02:00
Tamas Vajk
5418c95a01 Kotlin: minor refactoring in comment extraction 2022-08-30 15:43:48 +02:00
Erik Krogh Kristensen
72942afe3e Merge pull request #10220 from erik-krogh/overlapsWithNothing
print a correct range for ranges that doesn't contain any alpha-numeric chars
2022-08-30 15:38:34 +02:00
Tamas Vajk
9ced14672d Kotlin: Assign container class as the owner of init block comments 2022-08-30 15:37:55 +02:00
Tamas Vajk
d9b3726ee8 Kotlin: Add test case for doc comment on init block 2022-08-30 15:37:00 +02:00
Anders Schack-Mulligen
4070860d2b Merge pull request #10208 from aschackmull/java/dispatch-fixes
Java: A couple of small virtual dispatch fixes
2022-08-30 15:03:48 +02:00
Tamas Vajk
3513bb8eed Kotlin: Change Modifiable::isPublic to not cover Kotlin internal members 2022-08-30 14:37:27 +02:00
Michael Nebel
a726aec362 C#: Update change note based on review comment. 2022-08-30 14:34:55 +02:00
Michael Nebel
944a9e6130 C#: Provide change-note. 2022-08-30 14:34:54 +02:00
Michael Nebel
b85db2cc35 C#: Remove '--cil' flag from the dbscheme comments and add dummy upgrade and downgrade scripts. 2022-08-30 14:34:54 +02:00
Michael Nebel
27d1008171 C#: Update tracer arguments. 2022-08-30 14:34:54 +02:00
Michael Nebel
da214c89d6 C#: Update unit tests. 2022-08-30 14:34:54 +02:00
Michael Nebel
ea40e7b29d C#: Use the extractor option to decide, whether CIL should be enabled. 2022-08-30 14:34:54 +02:00
Michael Nebel
cc898e9b82 C#: Add extractor option parameter for enabling CIL. 2022-08-30 14:34:54 +02:00
Tamas Vajk
d9086e6328 Kotlin: Add test case for internal member accessed from java 2022-08-30 14:26:12 +02:00
Michael Nebel
e020ae77e0 Merge pull request #10158 from michaelnebel/csharp/narrowcollectiontypes
C#: Narrow collection like types in model generation.
2022-08-30 14:20:57 +02:00
Asger F
dd44187aed Sync files again 2022-08-30 14:08:33 +02:00
Asger F
b107dd6855 Fix typo: receiver step -> type step 2022-08-30 14:08:33 +02:00
Asger F
f8b1aa7e7e Also apply type step in getNodeFromSubPath 2022-08-30 14:08:33 +02:00
Asger F
51d6f752ab JS: Add partially failing test 2022-08-30 14:08:31 +02:00
Asger F
d5d1365104 Synchronize ApiGraphModels.qll 2022-08-30 14:07:37 +02:00
Asger F
654c4eea0f Add support for type steps 2022-08-30 14:07:37 +02:00
Asger F
ef627b4872 Add support for TypeVar[x] and typeVariable rows 2022-08-30 14:07:35 +02:00
Asger F
b414192dcc Bugfix pruning in package-pruning API graph models 2022-08-30 14:05:41 +02:00
Asger F
623531a719 Merge pull request #10206 from asgerf/js/js-mad-changes
JS: Some JS-specific MaD changes
2022-08-30 14:03:14 +02:00
erik-krogh
7fd426e748 print a correct range for ranges that doesn't contain any alpha-numeric chars 2022-08-30 13:57:11 +02:00
Asger F
f589520917 JS: Add tests 2022-08-30 13:38:08 +02:00
Geoffrey White
4984d8f6f2 Apply suggestions from code review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2022-08-30 12:26:06 +01:00
Geoffrey White
645364e8b8 Update swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.qhelp
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2022-08-30 12:24:49 +01:00
Ian Lynagh
f5d43b80ed Merge pull request #10193 from igfoo/igfoo/extractClassSupertypes
Kotlin: Small simplification
2022-08-30 11:52:02 +01:00
Ian Lynagh
f118b39844 Merge pull request #10192 from igfoo/igfoo/array
Kotlin: Remove another cast
2022-08-30 11:51:48 +01:00
Ian Lynagh
a5893f38c5 Merge pull request #10189 from igfoo/igfoo/substituteTypeAndArguments
Kotlin: Remove a cast from substituteTypeAndArguments
2022-08-30 11:51:39 +01:00
Ian Lynagh
d6bdc8c711 Merge pull request #10178 from igfoo/igfoo/AnyDbType
Kotlin: Add AnyDbType
2022-08-30 11:51:25 +01:00
Tony Torralba
1f83c5833b Merge pull request #10092 from zbazztian/zbazztian/string.replace-taint
Java: Add additional taint steps for java.lang.String methods
2022-08-30 12:24:37 +02:00
Paolo Tranquilli
55e5fa29cb Merge pull request #10219 from github/redsun82/swift-add-params-to-init-name
Swift: fix integration tests
2022-08-30 12:06:09 +02:00
Paolo Tranquilli
57b8830972 Swift: fix integration tests 2022-08-30 11:46:27 +02:00
Paolo Tranquilli
fc919841ed Merge pull request #10218 from github/redsun82/swift-add-params-to-init-name
Swift: make `ConstructorDecl`'s name include params
2022-08-30 11:34:56 +02:00
Nora Dimitrijević
ce1e4ad422 Merge branch 'main' into missing-check-scanf-squashed 2022-08-30 11:34:00 +02:00
Paolo Tranquilli
00755ecede Merge pull request #10217 from github/redsun82/swift-add-qlgen-docstring
Swift: add missing `qlgen.py` docstring
2022-08-30 11:19:09 +02:00
Nora Dimitrijević
e10042be7d C++: Improve docs based on doc-review
Thanks to @mchammer01 and @geoffw0 for the suggestions latest.
2022-08-30 11:14:57 +02:00
Paolo Tranquilli
38d65d3fae Swift: make ConstructorDecl's name include params
In order to distinguish overloads of the constructor and for consistency
with other function calls, `ConstructorDecl` string representation uses
the name which includes parentheses and parameter labels.

For consistency also the destructor got the same change, which means
all `DestructorDecl`s will now show as `deinit()` rather than `deinit`.
2022-08-30 11:11:50 +02:00
Paolo Tranquilli
75a7bcd3b1 Swift: add missing qlgen.py docstring 2022-08-30 11:03:23 +02:00
Mathias Vorreiter Pedersen
f5471e4e1a Merge pull request #10211 from github/redsun82/swift-generate-printast-first-step
Swift: generate indexed parent/child relationship
2022-08-30 09:55:05 +01:00
Paolo Tranquilli
9102cb5d0d Swift: make some ParentChild predicates private 2022-08-30 10:35:08 +02:00
Erik Krogh Kristensen
8f0b999c31 Merge pull request #10207 from erik-krogh/fixRank
fix performance issue in the ReDoS query
2022-08-30 10:17:11 +02:00
Paolo Tranquilli
beb0472811 Swift: fix ParentChild generation
There was an issue in case multiple inheritance from classes with
children was involved, where indexes would overlap.

The generated code structure has been reshuffled a bit, with
`Impl::getImmediateChildOf<Class>` predicates giving 0-based children
for a given class, including those coming from bases, and the final
`Impl::getImmediateChild` disjuncting the above on final classes only.

This removes the need of `getMaximumChildrenIndex<Class>`, and also
removes the code scanning alerts.

Also, comments were fixed addressing the review.
2022-08-30 10:15:11 +02:00
Erik Krogh Kristensen
25ee5545e6 Merge pull request #9751 from erik-krogh/dynCall
JS: add call-edge for dynamic dispatch to unknown property from an object literal
2022-08-30 10:07:08 +02:00
Erik Krogh Kristensen
c2679d8632 Merge pull request #10213 from erik-krogh/wayToLargeRange
put a limit on the length of the equivalent range in overly-large-range
2022-08-30 09:28:16 +02:00
erik-krogh
9963def300 update expected output of test that was failing on main. semantic merge conflict between #10202 and #10184 2022-08-30 09:15:36 +02:00
Anders Schack-Mulligen
4a2209752e Merge pull request #10214 from github/workflow/coverage/update
Update CSV framework coverage reports
2022-08-30 09:13:30 +02:00
github-actions[bot]
f2e37d25b3 Add changed framework coverage reports 2022-08-30 00:21:28 +00:00
Aditya Sharad
f175c60069 Apply suggestions from code review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
2022-08-29 12:26:35 -07:00
erik-krogh
f47b097d7c put a limit on the length of the equivalent range 2022-08-29 21:03:52 +02:00
Paolo Tranquilli
3f4a330658 Swift: make ParentChild::Impl module private 2022-08-29 17:35:16 +02:00
Paolo Tranquilli
f14f9375e0 Merge pull request #10210 from github/redsun82/swift-fix-double-parent
Swift: fix double parent
2022-08-29 17:27:57 +02:00
Paolo Tranquilli
20e94b8a38 Swift: add more tests for the generated parent-child relationship 2022-08-29 17:10:46 +02:00
Paolo Tranquilli
105c0d0dce Swift: update after generated parent-child changes 2022-08-29 17:10:46 +02:00
Paolo Tranquilli
b5aad04f65 Swift: add indexes to generated parent-child library 2022-08-29 17:10:46 +02:00
Paolo Tranquilli
7b50c958f7 Swift: fix Cfg.expected 2022-08-29 17:09:42 +02:00
erik-krogh
52b9ff81c5 Merge branch 'main' into dynCall 2022-08-29 15:30:01 +02:00
Erik Krogh Kristensen
27bc69883c Merge pull request #10184 from erik-krogh/ts48
JavaScript: Update to TypeScript 4.8
2022-08-29 15:03:32 +02:00
Anders Schack-Mulligen
e26a7fc4f3 Merge pull request #10173 from zbazztian/spring-crudrepository
Java: Add data flow model for Spring's CrudRepository.save() method
2022-08-29 15:00:07 +02:00
Paolo Tranquilli
4e453b1ac5 Swift: accept test changes 2022-08-29 14:57:03 +02:00
Paolo Tranquilli
0aecbc2a01 Swift: reorganize some children in schema.yml 2022-08-29 14:52:14 +02:00
Michael Nebel
e8d726606b C#/Java: Add descriptive comment on negative summaries in ExternalFlow. 2022-08-29 14:29:32 +02:00
Michael Nebel
91abf79404 Java: Update negative summaries where static initializers has been excluded. 2022-08-29 14:29:32 +02:00
Michael Nebel
2b1423dd74 Java: Exclude static initializers from model generation. 2022-08-29 14:29:32 +02:00
Michael Nebel
37aa6b2c5f C#: Add file level QL Doc. 2022-08-29 14:29:32 +02:00
Michael Nebel
dbfd16647b Java: Add negative model CSV validation test. 2022-08-29 14:29:32 +02:00
Michael Nebel
290c35e7c6 Java: Use negative summary models in unsupported external api telemetry query. 2022-08-29 14:28:55 +02:00
Michael Nebel
23e0ee66e0 Java: Add negative models for commons-io. 2022-08-29 14:28:55 +02:00
Michael Nebel
beb85c20f2 Java: Update commons-io generated positive models based on main. 2022-08-29 14:28:55 +02:00
Asger F
d6ee54eb09 Merge pull request #10202 from asgerf/js/typescript-conditional-types
JS: Enable type extraction inside conditional types again
2022-08-29 14:26:06 +02:00
Anders Schack-Mulligen
bd6acc0d75 Java: Refactor upcastCand, and track type flow for upcasts to unbound generics. 2022-08-29 13:57:39 +02:00
Anders Schack-Mulligen
fc415b32c2 Java: Bugfix in TypeFlow. 2022-08-29 13:50:13 +02:00
Anders Schack-Mulligen
e89b42fc11 Java: Allow dispatch to methods on abstract classes without subtypes. 2022-08-29 13:48:55 +02:00
erik-krogh
77949cbeb3 add context to the rankState predicate in ExponentialBackTracking.qll 2022-08-29 13:42:05 +02:00
Anders Schack-Mulligen
6e7dcfcc6e Merge pull request #10097 from aschackmull/java/unification
Java: Improve virtual dispatch via better unification check and deduplicate code with parameterised module
2022-08-29 13:28:04 +02:00
erik-krogh
b1e53280a6 fix that the wrong line got deleted 2022-08-29 13:26:02 +02:00
Erik Krogh Kristensen
bd5fd7d963 fix typo in change-note
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2022-08-29 13:25:54 +02:00
erik-krogh
56292cad26 don't modify the TypeScript nodes, instead forward illegalDecorators to the java extractor 2022-08-29 13:22:04 +02:00
erik-krogh
d0814aa37c Go: add change-note for go 2022-08-29 13:10:23 +02:00
erik-krogh
33ba01927f Go: add CWE tag and @security-severity tag to go/insecure-hostkeycallback 2022-08-29 13:10:23 +02:00
erik-krogh
f09fc7b0fc Java: add java change-note 2022-08-29 13:10:21 +02:00
erik-krogh
8b37168223 Java: remove security tag from queries not in the security folder and with missing security-severity tags 2022-08-29 13:08:56 +02:00
erik-krogh
f678c8a967 PY: add python change-note 2022-08-29 13:08:52 +02:00
erik-krogh
4353937bcf PY: add missing security tags on Python queries 2022-08-29 13:08:47 +02:00
Asger F
ea0ae98e58 JS: Use explicit this 2022-08-29 12:39:53 +02:00
erik-krogh
6aca9b9f49 fix support for illegal decorators in the TypeScript extractor 2022-08-29 12:14:58 +02:00
erik-krogh
50734c7c6a bump the TypeScript version in the list of supported languages 2022-08-29 12:14:58 +02:00
erik-krogh
e0ff27331f bump extractor version 2022-08-29 12:14:58 +02:00
erik-krogh
97ffd2d4d9 add change-note 2022-08-29 12:14:58 +02:00
erik-krogh
b7367ca649 update to TypeScript 4.8RC 2022-08-29 12:14:55 +02:00
Asger F
45d64c48e3 JS: Update test output 2022-08-29 12:01:47 +02:00
Anders Schack-Mulligen
adfd474fee Java: Move file. 2022-08-29 11:50:54 +02:00
Asger F
99f03a0d61 JS: Make API graphs take types from models into account 2022-08-29 10:14:56 +02:00
Asger F
d166727db9 JS: Add WithStringArgument[arg=const] filter 2022-08-29 10:14:56 +02:00
Asger F
4f3c8ec770 JS: Add AnyMember MaD token 2022-08-29 10:14:53 +02:00
Asger F
9887025af2 JS: Some minor fixes in Classes.qll 2022-08-29 10:14:53 +02:00
Erik Krogh Kristensen
68bf9f39b9 Merge pull request #10181 from erik-krogh/fixCons
QL: remove consistency errors related to resolving multiple predicates from parameterized modules
2022-08-29 09:40:07 +02:00
erik-krogh
dda16a0a30 add a isSignature() predicate to ClasslessPredicate 2022-08-29 09:17:40 +02:00
Ian Lynagh
4cd7bf2ebb Kotlin: Small simplification
Also removes a cast
2022-08-26 16:28:10 +01:00
Ian Lynagh
d2a5281d94 Kotlin: Remove another cast 2022-08-26 15:59:26 +01:00
Nick Rolfe
898689f550 Merge pull request #9896 from github/nickrolfe/hardcoded_code
Ruby: port js/hardcoded-data-interpreted-as-code
2022-08-26 13:49:25 +01:00
Paolo Tranquilli
7887f669c1 Merge pull request #10175 from github/redsun82/swift-missing-extractions
Swift: fix missing extractions
2022-08-26 14:09:09 +02:00
Ian Lynagh
131632e7c1 Kotlin: Remove a cast from substituteTypeAndArguments
It looks like it was safe, but it was hard to see why, and may
become unsafe following future kotlinc changes.
2022-08-26 13:06:05 +01:00
Paolo Tranquilli
b5d18b05e2 Swift: accept new module type in tests 2022-08-26 13:52:24 +02:00
AlexDenisov
bb167a3d77 Merge pull request #10187 from github/redsun82/swift-port-frontend-invocations-test-to-linux
Swift: port frontend-invocations test to linux
2022-08-26 12:53:19 +02:00
Paolo Tranquilli
c9b14b4459 Swift: address review comments 2022-08-26 12:49:19 +02:00
Paolo Tranquilli
ced36ffc61 Swift: run swift instead of swift-frontend on Linux 2022-08-26 12:12:21 +02:00
Paolo Tranquilli
c7c42acbf5 Swift: port frontend-invocations test to linux
`swift-frontend` will be in `$PATH` on Linux, and apparently it does
not require the `-sdk` option.
2022-08-26 12:03:18 +02:00
Anders Schack-Mulligen
3e5155d1a1 Java: Address review comments. 2022-08-26 11:45:01 +02:00
Paolo Tranquilli
ebc7432f46 Swift: implement imported_ and exported_modules
This has expanded the required builtin symbols.
2022-08-26 11:37:14 +02:00
Paolo Tranquilli
2e9d9cfb20 Swift: add imported modules properties to ModuleDecl 2022-08-26 11:23:02 +02:00
Paolo Tranquilli
a5a58d3dc5 Swift: start with loaded modules for extraction 2022-08-26 11:23:02 +02:00
Nick Rolfe
52d46552af Ruby: fix 'inefficient string comparison' alert 2022-08-26 09:58:22 +01:00
Erik Krogh Kristensen
c02387a25a Merge pull request #10153 from erik-krogh/more-acronyms
more renamings of acronyms to camelCase
2022-08-26 10:52:17 +02:00
Nick Rolfe
95bf18fdc9 Ruby: make hex-escaped strings ("\xCD\xEF" etc.) sources of hardcoded data 2022-08-26 09:33:03 +01:00
Paolo Tranquilli
0971ca6a82 Swift: emit <Builtin>.trap instead of .trap 2022-08-26 09:35:19 +02:00
Michael Nebel
f4835e3960 C#: Update flow summaries test cases based on the latest models. 2022-08-26 09:30:08 +02:00
Michael Nebel
e71ab59c9a C#: Update the generated models. 2022-08-26 09:30:07 +02:00
Michael Nebel
be4c2231d1 C#: Avoid generating new source models on 'file' kind sources. 2022-08-26 09:30:07 +02:00
Michael Nebel
a83ab79d31 C#: Update models based on relevant collection changes. 2022-08-26 09:30:07 +02:00
Michael Nebel
41274d9e5a C#: Update expected test output. 2022-08-26 09:30:07 +02:00
Michael Nebel
4bf41d0b81 C#: Update model generator to exclude models for some collection like types. 2022-08-26 09:30:07 +02:00
Michael Nebel
31dddef94e C#: Update all models prior to model generator change. 2022-08-26 09:30:07 +02:00
Michael Nebel
83b3125dea C#: Some test examples of collection like types that should be excluded. 2022-08-26 09:30:07 +02:00
Paolo Tranquilli
2c153f68e1 Swift: replace processed with seen in module visiting 2022-08-26 09:28:38 +02:00
Paolo Tranquilli
d5af30d28d Swift: add comment to getBuiltinDecls 2022-08-26 09:28:02 +02:00
Asger F
1a0abfa7a5 JS: Enable type extraction inside conditional types again 2022-08-26 09:27:53 +02:00
Tamás Vajk
4f5c06fed7 Merge pull request #10169 from tamasvajk/kotlin-array-iterator
Kotlin: fix array iterator extraction
2022-08-26 08:33:52 +02:00
Geoffrey White
2d57786dae Merge branch 'main' into cleartext 2022-08-25 23:10:36 +01:00
Geoffrey White
7fd64f1d9c Swift: Make QL-for-QL happy. 2022-08-25 23:06:03 +01:00
Geoffrey White
926da4bedc Swift: Query descriptions and metadata. 2022-08-25 22:52:19 +01:00
Geoffrey White
9a53a40ac6 Swift: Qhelp and examples for both queries. 2022-08-25 22:52:18 +01:00
Geoffrey White
2690732c75 Swift: Special cases to get taint flow working. 2022-08-25 22:15:19 +01:00
Geoffrey White
698a9e2e2e Swift: Realm database support. 2022-08-25 22:15:18 +01:00
Geoffrey White
3126fb930d Swift: Core Data support. 2022-08-25 22:15:18 +01:00
Geoffrey White
456ab980a5 Swift: Fix duplicate results. 2022-08-25 22:15:17 +01:00
Geoffrey White
0cd2efc1b1 Swift: CleartextTransmission query. 2022-08-25 22:15:16 +01:00
Geoffrey White
dacb7f5f25 Swift: Add a SensitiveExprs lib (and test it). 2022-08-25 22:15:15 +01:00
Geoffrey White
2aa6dd20ff Swift: Make tests more accurate and don't use 'pwd' as a variable name (it has alternative meanings so is not a good test). 2022-08-25 22:15:14 +01:00
Geoffrey White
1c5283628b Swift: Additional test cases. 2022-08-25 22:15:13 +01:00
erik-krogh
c225605ed7 QL: remove consistency errors related to resolving multiple predicates from parameterized modules 2022-08-25 21:43:30 +02:00
erik-krogh
1d1aa7c8b4 update some expected output 2022-08-25 20:52:30 +02:00
erik-krogh
4b06bca770 fixup getAPrimaryQlClass 2022-08-25 20:52:30 +02:00
erik-krogh
ebb1106d9d add missing qldoc 2022-08-25 20:52:30 +02:00
erik-krogh
cc7a9ef97a rename more acronyms 2022-08-25 20:52:27 +02:00
Ian Lynagh
5be8e45d09 Kotlin: Add AnyDbType
All DbType* types extend it, and `Label`s require their argument to be a
subtype of it.
2022-08-25 16:40:27 +01:00
Nora Dimitrijević
7d24d96d80 C++: Optimize MissingCheckScanf/bigStep() 2022-08-25 17:12:25 +02:00
Nora Dimitrijević
02772ed20c Revert changes to .gitignore and .clang-format
because they are potentially too global, belong in a separate PR.
2022-08-25 16:37:39 +02:00
Nora Dimitrijević
2bd866cc82 C++: improve change note and move to right place 2022-08-25 16:00:25 +02:00
Nora Dimitrijević
ad56274a73 C++: Small improvements to query qldoc and message 2022-08-25 15:22:41 +02:00
Erik Krogh Kristensen
06afe9c0f4 Merge pull request #9816 from erik-krogh/msgConsis
Make alert messages consistent across languages
2022-08-25 15:20:01 +02:00
Paolo Tranquilli
df3dc9677f Swift: fix missing extractions from Builtin
There were missing extractions from the Builtin (and other) modules.

This was actually caused by two issues:
* we did not visit all required modules, as for example the `Builtin`
  module does not appear as being imported by anybody (together with
  another mysterious `__Objc` module)
* moreover the `Builtin` module works internally by only creating
  declarations on demand, and does not provide a list of its top level
  declarations.

The first problem was solved by moving module collection to the actual
visiting. This may mean we extract less modules, as we only extract the
modules we actually use something from (recursively). This change can
be reverted if we feel we need it.

The second one was solved by explicitly listing the builtin symbols
encountered during a normal extraction. This does mean this list needs
to be kept up to date.
2022-08-25 15:18:24 +02:00
Nora Dimitrijević
a6a30b3725 C++: clarify ScanfOutput.getMinimumGuardConstant() 2022-08-25 15:07:39 +02:00
Nora Dimitrijević
e39229d59e C++: Remove unique-Instruction kludge in ScanfOutput
Passes tests.
2022-08-25 14:38:58 +02:00
Nora Dimitrijević
d8800c03b6 C++: new helper predicates in ScanfFunctionCall
Extract some of the logic from the `cpp/missing-check-scanf` query into
the more generally useful `getOutputArgument(int index)`, `getAnOutputArgument()`,
and `getNumberOfOutputArguments()` predicates.
2022-08-25 14:32:15 +02:00
Ian Lynagh
2e2621adad Merge pull request #10154 from igfoo/igfoo/findSubType
Kotlin: Implement and use fun <T,reified S: T> Iterable<T>.findSubType
2022-08-25 12:57:46 +01:00
Sebastian Bauersfeld
130e1892f4 Address review comments. 2022-08-25 18:49:38 +07:00
Sebastian Bauersfeld
207aebc581 Change wording of change note. 2022-08-25 18:47:36 +07:00
Sebastian Bauersfeld
36b5e5f61a Java: Add change notes. 2022-08-25 17:58:24 +07:00
Sebastian Bauersfeld
a486a89cee Java: Taint flow through org.springframework.data.repository.CrudRepository.save(). 2022-08-25 17:58:24 +07:00
Erik Krogh Kristensen
ba1ad00d2a Merge pull request #10062 from erik-krogh/redosPrefix
JS: use the shared regular expression libraries in `js/case-sensitive-middleware-path`
2022-08-25 12:57:16 +02:00
Nick Rolfe
acf5b11139 Merge remote-tracking branch 'origin/main' into nickrolfe/hardcoded_code 2022-08-25 11:44:55 +01:00
erik-krogh
c7aa58252a change "does not seem to check" to "does not check" in unchecked-cast-in-equals queries 2022-08-25 12:31:58 +02:00
Ian Lynagh
12eab3d7f0 Kotlin: Specialise findSubType to IrDeclaration
We only use it on that type, and this makes the uses a bit quieter.
2022-08-25 10:11:19 +01:00
Tamas Vajk
15305fd9bb Kotlin: Fix iterator extraction of IntArray, BooleanArray, ... 2022-08-25 11:05:17 +02:00
Tamas Vajk
7196fdd475 Kotlin: fix array iterator extraction to work outside of for loops 2022-08-25 09:23:34 +02:00
Tamas Vajk
af2614be84 Kotlin: Add array iterator tests 2022-08-25 09:17:50 +02:00
Paolo Tranquilli
606b9e6e38 Revert "Swift: rollback removal of std::variant"
This reverts commit 50d9a2e9cd.
2022-08-25 09:12:35 +02:00
Nora Dimitrijević
5c894ae40b Merge branch 'main' into missing-check-scanf-squashed 2022-08-24 21:14:57 +02:00
Nora Dimitrijević
6158ee1133 Change note 2022-08-24 21:09:24 +02:00
Nora Dimitrijević
170d12bf5a Write MissingCheckScanf.qhelp 2022-08-24 19:58:19 +02:00
Mathias Vorreiter Pedersen
f2d9393928 Swift: Only test local-flow step relations for nodes with proper location information. 2022-08-24 17:14:11 +01:00
erik-krogh
014dcd1454 fixup a Python query, it didn't select something with a location 2022-08-24 16:23:20 +02:00
erik-krogh
5d9b25c75d Merge branch 'main' into msgConsis 2022-08-24 16:19:32 +02:00
Mathias Vorreiter Pedersen
80bf22cf6f Swift: Accept test changes in query tests. 2022-08-24 14:52:36 +01:00
Mathias Vorreiter Pedersen
2d90940111 Swift: Add field flow. 2022-08-24 14:52:36 +01:00
erik-krogh
1c0f2251e2 Merge branch 'main' into msgConsis 2022-08-24 14:38:57 +02:00
Ian Lynagh
4cd90a15d0 Kotlin: Use findSubType in KotlinUsesExtractor too 2022-08-24 12:16:16 +01:00
Ian Lynagh
28d95f4d99 Kotlin: Implement and use fun <T,reified S: T> Iterable<T>.findSubType
We had a lot of uses of find which looked for a subtype, but then had to
cast (seemingly unsafely) the result to that subtype. This pulls all the
casts out into a utility function.
2022-08-24 12:10:53 +01:00
erik-krogh
f1799ae3d2 print the endpointExample in the alert-messsage, and only report one working example 2022-08-24 13:09:48 +02:00
Nora Dimitrijević
ca162a4365 C++: complete initial implementation of cpp/missing-check-scanf
There are still some remaining FPs (haven't fully tested them)
that should be ironed out in a follow-up to increase the precision, e.g.:

  * if scanf(&i) != 1 return
    if maybe() && scanf(&i) != 1 return
    use(i) // should be OK on both counts

  * The minimum guard constant for the *_s variants may not be right.

  * int i[2]
    scanf(i, i+1) // second i is flagged as a use of the first

  * Maybe loosen the "unguarded or badly guarded use() = bad" policy to
    "unguarded but already-initialized = good" and "badly guarded = bad",
    since a lot of FPs in MRVA fall into the "unguarded but already-
    initialized" bucket.
2022-08-24 11:25:06 +02:00
Nora Dimitrijević
69911d4f36 .clang-format: do not autoformat test.cpp 2022-08-24 11:25:05 +02:00
Anders Schack-Mulligen
92f2976399 Java: Improve unification check for wildcards with lower bounds. 2022-08-24 09:50:13 +02:00
Anders Schack-Mulligen
f248c6a11e Java: Improve unification check for bounded types. 2022-08-24 09:50:13 +02:00
Anders Schack-Mulligen
6b01f02df6 Java: Deduplicate unification code as a parameterised module. 2022-08-24 09:50:13 +02:00
erik-krogh
27fcc90a97 Merge branch 'main' into msgConsis 2022-08-24 09:21:43 +02:00
erik-krogh
a50234adb0 apply suggestion from review 2022-08-23 15:41:37 +02:00
erik-krogh
5e3cb08ed2 rename stateInPumpableRegexp to stateInRelevantRegexp 2022-08-23 12:40:45 +02:00
erik-krogh
1a7d3ee831 update expected output after changing queries 2022-08-23 12:35:32 +02:00
erik-krogh
afadcd9b45 use a more detailed alert message in bitwise-sign-check 2022-08-23 11:18:45 +02:00
erik-krogh
d96d6721ba change the alert message of unused-local-variable 2022-08-23 11:15:11 +02:00
erik-krogh
de8384d904 revert alert message change to java/unused-local-variable 2022-08-23 11:14:58 +02:00
erik-krogh
305a23b952 apply suggestion from review 2022-08-23 11:05:32 +02:00
erik-krogh
f7846a598e add change-notes 2022-08-23 07:54:01 +02:00
erik-krogh
7e0bd5bde4 update expected output of tests 2022-08-22 21:41:47 +02:00
erik-krogh
df9a9f4a56 update rb/stored-css to match javascript 2022-08-22 21:41:47 +02:00
erik-krogh
9b257bfa9e update rb/reflected-xss to match javascript 2022-08-22 21:41:47 +02:00
erik-krogh
ca299b9dc1 update py/unreachable-statement to match javascript/go 2022-08-22 21:41:47 +02:00
erik-krogh
31e15e27fc update py/unsafe-deserialization to match ruby/javascript/java 2022-08-22 21:41:47 +02:00
erik-krogh
778879908e update rb/code-injection to match python 2022-08-22 21:41:46 +02:00
erik-krogh
60908de089 update js/nested-loops-with-same-variable to match cpp 2022-08-22 21:41:46 +02:00
erik-krogh
20625ae60d update {js/go/py}/xpath-injection to match csharp/java 2022-08-22 21:41:46 +02:00
erik-krogh
b5458b2125 update js/insecure-randomness to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
9cdd8cc8f5 update js/tainted-format-string to match ruby/java 2022-08-22 21:41:46 +02:00
erik-krogh
9395f156de update {js/py}/command-line-injection to match csharp/java 2022-08-22 21:41:46 +02:00
erik-krogh
684a987abf update java/unused-import to match python 2022-08-22 21:41:46 +02:00
erik-krogh
54268f4424 update java/static-array to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
8899c1be04 update java/unassigned-field to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
280b101caa update java/useless-assignment-to-local to match go 2022-08-22 21:41:46 +02:00
erik-krogh
034d197e01 update {java/rb}/xxe to match python/javascript 2022-08-22 21:41:46 +02:00
erik-krogh
2d0a4c3d83 update {go/py}/stack-trace-exposure to match javascript 2022-08-22 21:41:46 +02:00
erik-krogh
5a0183f1e2 update java/password-in-configuration to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
151529d08f correct the query-id of the experimental go/pam-auth-bypass query 2022-08-22 21:41:46 +02:00
erik-krogh
b5f3cd7a55 update cs/useless-tostring-call to match java 2022-08-22 21:41:46 +02:00
erik-krogh
49a3e208d7 update cs/index-out-of-bounds to match javascript/go 2022-08-22 21:41:46 +02:00
erik-krogh
52171d6733 update cs/unchecked-cast-in-equals to match java 2022-08-22 21:41:46 +02:00
erik-krogh
ea11f744e1 update cs/confusing-override-name to match java 2022-08-22 21:41:46 +02:00
erik-krogh
064c9a6938 update {cs/java}/todo-comment to match javascript 2022-08-22 21:41:46 +02:00
erik-krogh
678e433013 update cpp/missing-case-in-switch to match java 2022-08-22 21:41:45 +02:00
erik-krogh
ea2777fa3e update {cs/cpp}/equality-on-floats to use the same alert-message/description 2022-08-22 21:41:45 +02:00
erik-krogh
55c8863e92 update java/sql-injection to match go/javascript/python/ruby 2022-08-22 21:41:45 +02:00
erik-krogh
3553f3d9b8 update {rb/py/js/go}/path-injection to match java/csharp 2022-08-22 21:41:45 +02:00
erik-krogh
39c1832995 update {cpp/js}/bitwise-sign-check to match java 2022-08-22 21:41:45 +02:00
erik-krogh
cc41a83a8d update {py/cpp}/commented-out-code to match csharp/java/javascript 2022-08-22 21:41:45 +02:00
erik-krogh
b471a401cc update {rb/js/java}/unused-parameter to match python 2022-08-22 21:41:45 +02:00
erik-krogh
698ccd8850 update {cpp/java}/unused-local to match python 2022-08-22 21:41:45 +02:00
erik-krogh
5a312cd0da update cpp/complex-block to match java/csharp 2022-08-22 21:41:45 +02:00
erik-krogh
b1c9843d15 update {cs/cpp}/empty-block so they have the same alert message 2022-08-22 21:41:45 +02:00
erik-krogh
594fbc678e update js/zip-slip to match java/go/csharp 2022-08-22 21:41:45 +02:00
erik-krogh
e52fa9a469 update {cs/java}/regex-injection to match javascript 2022-08-22 21:41:45 +02:00
luchua-bc
3e382fd47c Optimize the query 2022-08-22 17:04:03 +00:00
erik-krogh
049af68bc2 restrict suffix-construction to relevant regexps 2022-08-21 20:35:39 +02:00
erik-krogh
0aebc90b61 don't lowercase the endpointExample, and correctly handle root states 2022-08-21 18:38:47 +02:00
erik-krogh
bcf4c57060 Merge branch 'main' into redosPrefix 2022-08-19 19:22:49 +02:00
erik-krogh
d052b1e3c9 also support regular expressions without repetitions 2022-08-19 19:21:44 +02:00
Sebastian Bauersfeld
da79ad854c Added change notes. 2022-08-19 17:46:02 +07:00
Sebastian Bauersfeld
2ec3746861 Address PR comments. 2022-08-19 17:33:35 +07:00
Sebastian Bauersfeld
f6d42bd3c6 Allow blacklist sanitizers. 2022-08-19 17:33:35 +07:00
Sebastian Bauersfeld
11f527ea5b Fix up query tests. 2022-08-19 17:33:35 +07:00
Sebastian Bauersfeld
354a7fd252 Make taint flow through java.lang.String.(replace|replaceFirst|replaceAll) more permissive. 2022-08-19 17:33:35 +07:00
Sebastian Bauersfeld
5cf320d553 Add corresponding taint steps. 2022-08-19 17:33:35 +07:00
Sebastian Bauersfeld
b0fbe3658d Add java.lang.String taint tests. 2022-08-19 17:33:35 +07:00
erik-krogh
26fcf6b25b apply suggestions from review 2022-08-18 15:00:57 +02:00
erik-krogh
de3e1c39e4 use the shared regular expression libraries in js/case-sensitive-middleware-path 2022-08-18 10:07:55 +02:00
erik-krogh
473bc92e2d move the PrefixConstruction module out of the ReDoSPruning module 2022-08-18 10:07:48 +02:00
Tony Torralba
1d12bd1521 Share SpringUrlRedirect library 2022-08-17 10:43:43 +02:00
Geoffrey White
dd51b7f356 Swift: Add many tests. 2022-08-16 10:04:00 +01:00
Geoffrey White
c1be060ef8 Swift: Create query + test stubs. 2022-08-11 16:10:18 +01:00
erik-krogh
4cbfbfe170 add call-edge for dynamic dispatch to unknown property from an object literal 2022-08-11 12:29:50 +02:00
Geoffrey White
c62ae3b350 C++: First working. We now prefer flagging the cases where the variable was initialized, as in real world cases we haven't seen it done safely. 2022-08-11 12:27:48 +02:00
Geoffrey White
76ef779f60 C++: Add test and placeholder query. 2022-08-11 12:27:39 +02:00
Nora Dimitrijević
94c43c07c7 Update .gitignore for .vscode/*.log temporaries
These keep getting added, by the Makefile extension I believe.
2022-08-11 12:18:37 +02:00
Aditya Sharad
c0da29b204 Docs: Add spacing to fix list formatting 2022-08-10 11:16:41 -07:00
Aditya Sharad
231178d858 Docs: Add CodeQL standard packs and bundle to CodeQL tools page
Include links to changelogs, releases, and source code.
2022-08-10 10:49:19 -07:00
luchua-bc
b69eba9238 Add check for Spring redirect 2022-07-29 01:59:47 +00:00
luchua-bc
1ce31ec32c Add sinks of servlet dispatcher and filter 2022-07-26 23:05:25 +00:00
Nick Rolfe
6356b20928 Ruby: port js/hardcoded-data-interpreted-as-code 2022-07-26 16:05:22 +01:00
luchua-bc
962069ccff Add path check in a security context (redirect) 2022-07-22 23:10:52 +00:00
luchua-bc
48f143e7d4 Query to detect regex dot bypass 2022-07-20 22:39:24 +00:00
624 changed files with 28903 additions and 11270 deletions

View File

@@ -462,9 +462,6 @@
],
"SSA C#": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/SsaImplCommon.qll"
@@ -584,22 +581,22 @@
],
"Swift declarations test file": [
"swift/ql/test/extractor-tests/declarations/declarations.swift",
"swift/ql/test/library-tests/parent/declarations.swift"
"swift/ql/test/library-tests/ast/declarations.swift"
],
"Swift statements test file": [
"swift/ql/test/extractor-tests/statements/statements.swift",
"swift/ql/test/library-tests/parent/statements.swift"
"swift/ql/test/library-tests/ast/statements.swift"
],
"Swift expressions test file": [
"swift/ql/test/extractor-tests/expressions/expressions.swift",
"swift/ql/test/library-tests/parent/expressions.swift"
"swift/ql/test/library-tests/ast/expressions.swift"
],
"Swift patterns test file": [
"swift/ql/test/extractor-tests/patterns/patterns.swift",
"swift/ql/test/library-tests/parent/patterns.swift"
"swift/ql/test/library-tests/ast/patterns.swift"
],
"IncompleteMultiCharacterSanitization JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll",
"ruby/ql/lib/codeql/ruby/security/IncompleteMultiCharacterSanitizationQuery.qll"
]
}
}

View File

@@ -1,5 +1,3 @@
## 0.3.5
## 0.3.4
### Deprecated APIs

View File

@@ -1 +0,0 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.5
lastReleaseVersion: 0.3.4

View File

@@ -204,6 +204,7 @@ private class BinarySignExpr extends FlowSignExpr {
}
}
pragma[nomagic]
private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) {
binary.getLeftOperand() = left and binary.getRightOperand() = right
}

View File

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

View File

@@ -404,7 +404,10 @@ class Class extends UserType {
* compiled for. For this reason, the `is_pod_class` predicate is
* generated by the extractor.
*/
predicate isPOD() { is_pod_class(underlyingElement(this)) }
predicate isPod() { is_pod_class(underlyingElement(this)) }
/** DEPRECATED: Alias for isPod */
deprecated predicate isPOD() { this.isPod() }
/**
* Holds if this class, struct or union is a standard-layout class

View File

@@ -79,17 +79,17 @@ predicate isAggregateType03(Type t) {
* user-defined copy assignment operator and no user-defined destructor.
* A POD class is a class that is either a POD-struct or a POD-union.
*/
predicate isPODClass03(Class c) {
predicate isPodClass03(Class c) {
isAggregateClass03(c) and
not exists(Variable v |
v.getDeclaringType() = c and
not v.isStatic()
|
not isPODType03(v.getType())
not isPodType03(v.getType())
or
exists(ArrayType at |
at = v.getType() and
not isPODType03(at.getBaseType())
not isPodType03(at.getBaseType())
)
or
v.getType() instanceof ReferenceType
@@ -104,6 +104,9 @@ predicate isPODClass03(Class c) {
)
}
/** DEPRECATED: Alias for isPodClass03 */
deprecated predicate isPODClass03 = isPodClass03/1;
/**
* Holds if `t` is a POD type, according to the rules specified in
* C++03 3.9(10):
@@ -112,14 +115,17 @@ predicate isPODClass03(Class c) {
* such types and cv-qualified versions of these types (3.9.3) are
* collectively called POD types.
*/
predicate isPODType03(Type t) {
predicate isPodType03(Type t) {
exists(Type ut | ut = t.getUnderlyingType() |
isScalarType03(ut)
or
isPODClass03(ut)
isPodClass03(ut)
or
exists(ArrayType at | at = ut and isPODType03(at.getBaseType()))
exists(ArrayType at | at = ut and isPodType03(at.getBaseType()))
or
isPODType03(ut.(SpecifiedType).getUnspecifiedType())
isPodType03(ut.(SpecifiedType).getUnspecifiedType())
)
}
/** DEPRECATED: Alias for isPodType03 */
deprecated predicate isPODType03 = isPodType03/1;

View File

@@ -238,7 +238,7 @@ predicate dependsOnTransitive(DependsSource src, Element dest) {
/**
* A dependency that targets a TypeDeclarationEntry.
*/
private predicate dependsOnTDE(Element src, Type t, TypeDeclarationEntry dest) {
private predicate dependsOnTde(Element src, Type t, TypeDeclarationEntry dest) {
dependsOnTransitive(src, t) and
getDeclarationEntries(t, dest)
}
@@ -247,8 +247,8 @@ private predicate dependsOnTDE(Element src, Type t, TypeDeclarationEntry dest) {
* A dependency that targets a visible TypeDeclarationEntry.
*/
pragma[noopt]
private predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry dest) {
dependsOnTDE(src, t, dest) and
private predicate dependsOnVisibleTde(Element src, Type t, TypeDeclarationEntry dest) {
dependsOnTde(src, t, dest) and
exists(File g | g = dest.getFile() |
exists(File f | f = src.getFile() | f.getAnIncludedFile*() = g)
)
@@ -260,8 +260,8 @@ private predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry
private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest) {
exists(Type t |
// dependency from a Type use -> unique visible TDE
dependsOnVisibleTDE(src, t, dest) and
strictcount(TypeDeclarationEntry alt | dependsOnVisibleTDE(src, t, alt)) = 1
dependsOnVisibleTde(src, t, dest) and
strictcount(TypeDeclarationEntry alt | dependsOnVisibleTde(src, t, alt)) = 1
)
or
exists(TypedefType mid |

View File

@@ -1,11 +1,14 @@
import semmle.code.cpp.Macro
/** A macro defining NULL. */
class NULLMacro extends Macro {
NULLMacro() { this.getHead() = "NULL" }
class NullMacro extends Macro {
NullMacro() { this.getHead() = "NULL" }
}
/** DEPRECATED: Alias for NullMacro */
deprecated class NULLMacro = NullMacro;
/** A use of the NULL macro. */
class NULL extends Literal {
NULL() { exists(NULLMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) }
NULL() { exists(NullMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) }
}

View File

@@ -143,6 +143,28 @@ class ScanfFunctionCall extends FunctionCall {
* (rather than a `char*`).
*/
predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
/**
* Gets the output argument at position `n` in the vararg list of this call.
*
* The range of `n` is from `0` to `this.getNumberOfOutputArguments() - 1`.
*/
Expr getOutputArgument(int n) {
result = this.getArgument(this.getTarget().getNumberOfParameters() + n) and
n >= 0
}
/**
* Gets an output argument given to this call in vararg position.
*/
Expr getAnOutputArgument() { result = this.getOutputArgument(_) }
/**
* Gets the number of output arguments present in this call.
*/
int getNumberOfOutputArguments() {
result = this.getNumberOfArguments() - this.getTarget().getNumberOfParameters()
}
}
/**

View File

@@ -474,7 +474,7 @@ module FlowVar_internal {
}
/** Type-specialized version of `getEnclosingElement`. */
private ControlFlowNode getCFNParent(ControlFlowNode node) { result = node.getEnclosingElement() }
private ControlFlowNode getCfnParent(ControlFlowNode node) { result = node.getEnclosingElement() }
/**
* A for-loop or while-loop whose condition is always true upon entry but not
@@ -526,7 +526,7 @@ module FlowVar_internal {
}
private predicate bbInLoopCondition(BasicBlock bb) {
getCFNParent*(bb.getANode()) = this.(Loop).getCondition()
getCfnParent*(bb.getANode()) = this.(Loop).getCondition()
}
private predicate bbInLoop(BasicBlock bb) {

View File

@@ -1,18 +0,0 @@
private import semmle.code.cpp.ir.IR
private import SsaInternals as Ssa
class BasicBlock = IRBlock;
class SourceVariable = Ssa::SourceVariable;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends IRBlock {
ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction }
}
predicate variableWrite = Ssa::variableWrite/4;
predicate variableRead = Ssa::variableRead/4;

View File

@@ -1,10 +1,10 @@
import SsaImplCommon
private import cpp as Cpp
private import semmle.code.cpp.ir.IR
private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import SsaImplCommon as SsaImplCommon
private module SourceVariables {
private newtype TSourceVariable =
@@ -38,8 +38,6 @@ private module SourceVariables {
}
}
import SourceVariables
cached
private newtype TDefOrUse =
TExplicitDef(Instruction store) { explicitWrite(_, store, _) } or
@@ -86,7 +84,7 @@ abstract class Def extends DefOrUse {
Instruction getInstruction() { result = store }
/** Gets the variable that is defined by this definition. */
abstract SourceVariable getSourceVariable();
abstract SourceVariables::SourceVariable getSourceVariable();
/** Holds if this definition is guaranteed to happen. */
abstract predicate isCertain();
@@ -103,10 +101,10 @@ abstract class Def extends DefOrUse {
private class ExplicitDef extends Def, TExplicitDef {
ExplicitDef() { this = TExplicitDef(store) }
override SourceVariable getSourceVariable() {
override SourceVariables::SourceVariable getSourceVariable() {
exists(VariableInstruction var |
explicitWrite(_, this.getInstruction(), var) and
result.(SourceIRVariable).getIRVariable() = var.getIRVariable()
result.(SourceVariables::SourceIRVariable).getIRVariable() = var.getIRVariable()
)
}
@@ -116,11 +114,11 @@ private class ExplicitDef extends Def, TExplicitDef {
private class ParameterDef extends Def, TInitializeParam {
ParameterDef() { this = TInitializeParam(store) }
override SourceVariable getSourceVariable() {
result.(SourceIRVariable).getIRVariable() =
override SourceVariables::SourceVariable getSourceVariable() {
result.(SourceVariables::SourceIRVariable).getIRVariable() =
store.(InitializeParameterInstruction).getIRVariable()
or
result.(SourceIRVariableIndirection).getUnderlyingIRVariable() =
result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() =
store.(InitializeIndirectionInstruction).getIRVariable()
}
@@ -138,7 +136,7 @@ abstract class Use extends DefOrUse {
override string toString() { result = "Use" }
/** Gets the variable that is used by this use. */
abstract SourceVariable getSourceVariable();
abstract SourceVariables::SourceVariable getSourceVariable();
override IRBlock getBlock() { result = use.getUse().getBlock() }
@@ -148,12 +146,14 @@ abstract class Use extends DefOrUse {
private class ExplicitUse extends Use, TExplicitUse {
ExplicitUse() { this = TExplicitUse(use) }
override SourceVariable getSourceVariable() {
override SourceVariables::SourceVariable getSourceVariable() {
exists(VariableInstruction var |
use.getDef() = var and
if use.getUse() instanceof ReadSideEffectInstruction
then result.(SourceIRVariableIndirection).getUnderlyingIRVariable() = var.getIRVariable()
else result.(SourceIRVariable).getIRVariable() = var.getIRVariable()
then
result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() =
var.getIRVariable()
else result.(SourceVariables::SourceIRVariable).getIRVariable() = var.getIRVariable()
)
}
}
@@ -161,10 +161,11 @@ private class ExplicitUse extends Use, TExplicitUse {
private class ReturnParameterIndirection extends Use, TReturnParamIndirection {
ReturnParameterIndirection() { this = TReturnParamIndirection(use) }
override SourceVariable getSourceVariable() {
override SourceVariables::SourceVariable getSourceVariable() {
exists(ReturnIndirectionInstruction ret |
returnParameterIndirection(use, ret) and
result.(SourceIRVariableIndirection).getUnderlyingIRVariable() = ret.getIRVariable()
result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() =
ret.getIRVariable()
)
}
}
@@ -610,27 +611,45 @@ private module Cached {
import Cached
/**
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
exists(Def def |
def.hasIndexInBlock(bb, i) and
v = def.getSourceVariable() and
(if def.isCertain() then certain = true else certain = false)
)
private module SsaInput implements SsaImplCommon::InputSig {
private import semmle.code.cpp.ir.IR
class BasicBlock = IRBlock;
class SourceVariable = SourceVariables::SourceVariable;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends IRBlock {
ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction }
}
/**
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
exists(Def def |
def.hasIndexInBlock(bb, i) and
v = def.getSourceVariable() and
(if def.isCertain() then certain = true else certain = false)
)
}
/**
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(Use use |
use.hasIndexInBlock(bb, i) and
v = use.getSourceVariable() and
certain = true
)
}
}
/**
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
exists(Use use |
use.hasIndexInBlock(bb, i) and
v = use.getSourceVariable() and
certain = true
)
}
import SsaImplCommon::Make<SsaInput>

View File

@@ -165,7 +165,7 @@ private ControlFlowNode mostRecentSideEffect(ControlFlowNode node) {
/** Used to represent the "global value number" of an expression. */
cached
private newtype GVNBase =
private newtype GvnBase =
GVN_IntConst(int val, Type t) { mk_IntConst(val, t, _) } or
GVN_FloatConst(float val, Type t) { mk_FloatConst(val, t, _) } or
// If the local variable does not have a defining value, then
@@ -221,8 +221,8 @@ private newtype GVNBase =
* expression with this `GVN` and using its `toString` and `getLocation`
* methods.
*/
class GVN extends GVNBase {
GVN() { this instanceof GVNBase }
class GVN extends GvnBase {
GVN() { this instanceof GvnBase }
/** Gets an expression that has this GVN. */
Expr getAnExpr() { this = globalValueNumber(result) }

View File

@@ -63,17 +63,17 @@ class VariableDeclarationLine extends TVariableDeclarationInfo {
/**
* Gets a `VariableDeclarationEntry` on this line.
*/
VariableDeclarationEntry getAVDE() { vdeInfo(result, c, f, line) }
VariableDeclarationEntry getAVde() { vdeInfo(result, c, f, line) }
/**
* Gets the start column of the first `VariableDeclarationEntry` on this line.
*/
int getStartColumn() { result = min(this.getAVDE().getLocation().getStartColumn()) }
int getStartColumn() { result = min(this.getAVde().getLocation().getStartColumn()) }
/**
* Gets the end column of the last `VariableDeclarationEntry` on this line.
*/
int getEndColumn() { result = max(this.getAVDE().getLocation().getEndColumn()) }
int getEndColumn() { result = max(this.getAVde().getLocation().getEndColumn()) }
/**
* Gets the rank of this `VariableDeclarationLine` in its file and class
@@ -134,13 +134,13 @@ class VariableDeclarationGroup extends VariableDeclarationLine {
count(VariableDeclarationLine l |
l = this.getProximateNext*()
|
l.getAVDE().getVariable().getName()
l.getAVde().getVariable().getName()
)
}
override string toString() {
this.getCount() = 1 and
result = "declaration of " + this.getAVDE().getVariable().getName()
result = "declaration of " + this.getAVde().getVariable().getName()
or
this.getCount() > 1 and
result = "group of " + this.getCount() + " fields here"

View File

@@ -29,7 +29,4 @@ where
n = strictcount(ComplexStmt s | s = b.getAStmt()) and
n > 3 and
complexStmt = b.getAStmt()
select b,
"Block with too many statements (" + n.toString() +
" complex statements in the block). Complex statements at: $@", complexStmt,
complexStmt.toString()
select b, "Block with too many statements (" + n.toString() + " complex statements in the block)."

View File

@@ -110,4 +110,4 @@ where
emptyBlock(s, eb) and
not emptyBlockContainsNonchild(eb) and
not lineComment(eb)
select eb, "Empty block without comment"
select eb, "Empty block without comment."

View File

@@ -16,7 +16,7 @@ import cpp
class JumpTarget extends Stmt {
JumpTarget() { exists(GotoStmt g | g.getTarget() = this) }
FunctionDeclarationEntry getFDE() { result.getBlock() = this.getParentStmt+() }
FunctionDeclarationEntry getFde() { result.getBlock() = this.getParentStmt+() }
predicate isForward() {
exists(GotoStmt g | g.getTarget() = this |
@@ -33,8 +33,8 @@ class JumpTarget extends Stmt {
from FunctionDeclarationEntry fde, int nforward, int nbackward
where
nforward = strictcount(JumpTarget t | t.getFDE() = fde and t.isForward()) and
nbackward = strictcount(JumpTarget t | t.getFDE() = fde and t.isBackward()) and
nforward = strictcount(JumpTarget t | t.getFde() = fde and t.isForward()) and
nbackward = strictcount(JumpTarget t | t.getFde() = fde and t.isBackward()) and
nforward != 1 and
nbackward != 1
select fde,

View File

@@ -1,5 +1,3 @@
## 0.3.4
## 0.3.3
### Minor Analysis Improvements

View File

@@ -0,0 +1,17 @@
{
int i, j, r;
r = scanf("%d %d", &i, &j);
use(i); // BAD: i is not guarded
if (r >= 1) {
use(i); // GOOD: i is guarded correctly
use(j); // BAD: j is guarded incorrectly
}
if (r != 2)
return;
use(j); // GOOD: j is guarded correctly
}

View File

@@ -0,0 +1,51 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This query finds calls of <tt>scanf</tt>-like functions with missing or
improper return-value checking.
</p>
<p>
Specifically, the query flags uses of variables that may have been modified by
<tt>scanf</tt> and subsequently are used without being guarded by a correct
return-value check. A proper check is one that ensures that the corresponding
<tt>scanf</tt> has returned (at least) a certain minimum constant.
</p>
<p>
Functions in the <tt>scanf</tt> family return either EOF (a negative value)
in case of IO failure, or the number of items successfully read from the
input. Consequently, a simple check that the return value is truthy (nonzero)
is not enough.
</p>
<warning>
This query has medium precision because, in the current implementation, it
takes a strict stance on unguarded uses of output variables, and flags them
as problematic even if they have already been initialized.
</warning>
</overview>
<recommendation>
<p>
Ensure that all subsequent uses of <tt>scanf</tt> output arguments occur in a
branch of an <tt>if</tt> statement (or similar), in which it is known that the
corresponding <tt>scanf</tt> call has in fact read all possible items from its
input. This can be done by comparing the return value to a numerical constant.
</p>
</recommendation>
<example>
<p>This example shows different ways of guarding a <tt>scanf</tt> output:
</p>
<sample src="MissingCheckScanf.cpp" />
</example>
<references>
<li>SEI CERT C++ Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR62-CPP.+Detect+errors+when+converting+a+string+to+a+number">ERR62-CPP. Detect errors when converting a string to a number</a>.</li>
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/ERR33-C.+Detect+and+handle+standard+library+errors">ERR33-C. Detect and handle standard library errors</a>.</li>
<li>cppreference.com: <a href="https://en.cppreference.com/w/c/io/fscanf">scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,122 @@
/**
* @name Missing return-value check for a 'scanf'-like function
* @description Failing to check that a call to 'scanf' actually writes to an
* output variable can lead to unexpected behavior at reading time.
* @kind problem
* @problem.severity warning
* @security-severity 7.5
* @precision medium
* @id cpp/missing-check-scanf
* @tags security
* correctness
* external/cwe/cwe-252
* external/cwe/cwe-253
*/
import cpp
import semmle.code.cpp.commons.Scanf
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.ValueNumbering
/** An expression appearing as an output argument to a `scanf`-like call */
class ScanfOutput extends Expr {
ScanfFunctionCall call;
int varargIndex;
Instruction instr;
ValueNumber valNum;
ScanfOutput() {
this = call.getOutputArgument(varargIndex).getFullyConverted() and
instr.getConvertedResultExpression() = this and
valueNumber(instr) = valNum
}
ScanfFunctionCall getCall() { result = call }
/**
* Returns the smallest possible `scanf` return value that would indicate
* success in writing this output argument.
*/
int getMinimumGuardConstant() {
result =
varargIndex + 1 -
count(ScanfFormatLiteral f, int n |
// Special case: %n writes to an argument without reading any input.
// It does not increase the count returned by `scanf`.
n <= varargIndex and f.getUse() = call and f.getConversionChar(n) = "n"
)
}
predicate hasGuardedAccess(Access e, boolean isGuarded) {
e = this.getAnAccess() and
if
exists(int value, int minGuard | minGuard = this.getMinimumGuardConstant() |
e.getBasicBlock() = blockGuardedBy(value, "==", call) and minGuard <= value
or
e.getBasicBlock() = blockGuardedBy(value, "<", call) and minGuard - 1 <= value
or
e.getBasicBlock() = blockGuardedBy(value, "<=", call) and minGuard <= value
)
then isGuarded = true
else isGuarded = false
}
/**
* Get a subsequent access of the same underlying storage,
* but before it gets reset or reused in another `scanf` call.
*/
Access getAnAccess() {
exists(Instruction dst |
this.bigStep() = dst and
dst.getAst() = result and
valueNumber(dst) = valNum
)
}
private Instruction bigStep() {
result = this.smallStep(instr)
or
exists(Instruction i | i = this.bigStep() | result = this.smallStep(i))
}
private Instruction smallStep(Instruction i) {
instr.getASuccessor*() = i and
i.getASuccessor() = result and
not this.isBarrier(result)
}
private predicate isBarrier(Instruction i) {
valueNumber(i) = valNum and
exists(Expr e | i.getAst() = e |
i = any(StoreInstruction s).getDestinationAddress()
or
[e, e.getParent().(AddressOfExpr)] instanceof ScanfOutput
)
}
}
/** Returns a block guarded by the assertion of `value op call` */
BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
exists(GuardCondition g, Expr left, Expr right |
right = g.getAChild() and
value = left.getValue().toInt() and
DataFlow::localExprFlow(call, right)
|
g.ensuresEq(left, right, 0, result, true) and op = "=="
or
g.ensuresLt(left, right, 0, result, true) and op = "<"
or
g.ensuresLt(left, right, 1, result, true) and op = "<="
)
}
from ScanfOutput output, ScanfFunctionCall call, Access access
where
output.getCall() = call and
output.hasGuardedAccess(access, false)
select access,
"$@ is read here, but may not have been written. " +
"It should be guarded by a check that the $@ returns at least " +
output.getMinimumGuardConstant() + ".", access, access.toString(), call, call.toString()

View File

@@ -12,4 +12,4 @@
import CommentedOutCode
from CommentedOutCode comment
select comment, "This comment appears to contain commented-out code"
select comment, "This comment appears to contain commented-out code."

View File

@@ -1,7 +1,6 @@
/**
* @name Sign check of bitwise operation
* @description Checking the sign of a bitwise operation often has surprising
* edge cases.
* @description Checking the sign of the result of a bitwise operation may yield unexpected results.
* @kind problem
* @problem.severity warning
* @precision high
@@ -26,4 +25,4 @@ where
forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and
// exception for cases involving macros
not e.isAffectedByMacro()
select e, "Potential unsafe sign check of a bitwise operation."
select e, "Potentially unsafe sign check of a bitwise operation."

View File

@@ -21,4 +21,4 @@ where
FloatingPointType and
not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives
not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison
select ro, "Equality test on floating point values may not behave as expected."
select ro, "Equality checks on floating point values can yield unexpected results."

View File

@@ -13,10 +13,11 @@
import cpp
from EnumSwitch es, float missing, float total
from EnumSwitch es, float missing, float total, EnumConstant case
where
not es.hasDefaultCase() and
missing = count(es.getAMissingCase()) and
total = missing + count(es.getASwitchCase()) and
missing / total < 0.3
select es, "Switch statement is missing case for " + es.getAMissingCase().getName()
missing / total < 0.3 and
case = es.getAMissingCase()
select es, "Switch statement does not have a case for $@.", case, case.getName()

View File

@@ -163,46 +163,19 @@ TGlobalAddress globalAddress(Instruction instr) {
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
}
/**
* Gets a first `StoreInstruction` that writes to address `globalAddress` reachable
* from `block`.
*/
StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) {
1 = getStoreRank(result, block, globalAddress)
or
not exists(getStoreRank(_, block, globalAddress)) and
result = getFirstStore(block.getASuccessor(), globalAddress)
}
/**
* Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the
* first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.)
*/
int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) {
blockStoresToAddress(block, _, store, globalAddress) and
store =
rank[result](StoreInstruction anotherStore, int i |
blockStoresToAddress(_, i, anotherStore, globalAddress)
|
anotherStore order by i
)
}
/**
* Gets a next subsequent `StoreInstruction` to write to `globalAddress`
* after `store` has done so.
*/
StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) {
exists(IRBlock block, int rnk |
rnk = getStoreRank(store, block, globalAddress) and
rnk + 1 = getStoreRank(result, block, globalAddress)
/** Gets a `StoreInstruction` that may be executed after executing `store`. */
pragma[inline]
StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) {
exists(IRBlock block, int index1, int index2 |
block.getInstruction(index1) = store and
block.getInstruction(index2) = result and
index2 > index1
)
or
exists(IRBlock block, int rnk, IRBlock succ |
rnk = getStoreRank(store, block, globalAddress) and
not rnk + 1 = getStoreRank(_, block, globalAddress) and
succ = block.getASuccessor() and
result = getFirstStore(succ, globalAddress)
exists(IRBlock block1, IRBlock block2 |
store.getBlock() = block1 and
result.getBlock() = block2 and
block1.getASuccessor+() = block2
)
}
@@ -219,7 +192,7 @@ predicate stackAddressEscapes(
stackPointerFlowsToUse(store.getSourceValue(), vai)
) and
// Ensure there's no subsequent store that overrides the global address.
not exists(getANextStoreTo(store, globalAddress))
not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress())
}
predicate blockStoresToAddress(

View File

@@ -13,7 +13,7 @@ import SAL
from Parameter p, Call c, Expr arg
where
any(SALNotNull a).getDeclaration() = p and
any(SalNotNull a).getDeclaration() = p and
c.getTarget() = p.getFunction() and
arg = c.getArgument(p.getIndex()) and
nullValue(arg)

View File

@@ -18,7 +18,7 @@ from Function f, FunctionCall call
where
call.getTarget() = f and
call instanceof ExprInVoidContext and
any(SALCheckReturn a).getDeclaration() = f and
any(SalCheckReturn a).getDeclaration() = f and
not getOptions().okToIgnoreReturnValue(call)
select call, "Return value of $@ discarded although a SAL annotation " + "requires inspecting it.",
f, f.getName()

View File

@@ -11,7 +11,7 @@ import SAL
/** Holds if `e` has SAL annotation `name`. */
predicate hasAnnotation(DeclarationEntry e, string name) {
exists(SALAnnotation a |
exists(SalAnnotation a |
a.getMacro().getName() = name and
a.getDeclarationEntry() = e
)
@@ -21,7 +21,7 @@ predicate hasAnnotation(DeclarationEntry e, string name) {
predicate inheritsDeclAnnotations(DeclarationEntry e) {
// Is directly annotated
e.isDefinition() and
exists(SALAnnotation a | a.getMacro().getName() = "_Use_decl_annotations_" |
exists(SalAnnotation a | a.getMacro().getName() = "_Use_decl_annotations_" |
a.getDeclarationEntry() = e
)
or

View File

@@ -8,8 +8,8 @@ import cpp
/**
* A SAL macro defined in `sal.h` or a similar header file.
*/
class SALMacro extends Macro {
SALMacro() {
class SalMacro extends Macro {
SalMacro() {
this.getFile().getBaseName() =
["sal.h", "specstrings_strict.h", "specstrings.h", "w32p.h", "minwindef.h"] and
(
@@ -22,15 +22,18 @@ class SALMacro extends Macro {
}
}
/** DEPRECATED: Alias for SalMacro */
deprecated class SALMacro = SalMacro;
pragma[noinline]
private predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) }
/**
* An invocation of a SAL macro (excluding invocations inside other macros).
*/
class SALAnnotation extends MacroInvocation {
SALAnnotation() {
this.getMacro() instanceof SALMacro and
class SalAnnotation extends MacroInvocation {
SalAnnotation() {
this.getMacro() instanceof SalMacro and
isTopLevelMacroAccess(this)
}
@@ -47,23 +50,29 @@ class SALAnnotation extends MacroInvocation {
}
}
/** DEPRECATED: Alias for SalAnnotation */
deprecated class SALAnnotation = SalAnnotation;
/**
* A SAL macro indicating that the return value of a function should always be
* checked.
*/
class SALCheckReturn extends SALAnnotation {
SALCheckReturn() {
this.getMacro().(SALMacro).getName() = ["_Check_return_", "_Must_inspect_result_"]
class SalCheckReturn extends SalAnnotation {
SalCheckReturn() {
this.getMacro().(SalMacro).getName() = ["_Check_return_", "_Must_inspect_result_"]
}
}
/** DEPRECATED: Alias for SalCheckReturn */
deprecated class SALCheckReturn = SalCheckReturn;
/**
* A SAL macro indicating that a pointer variable or return value should not be
* `NULL`.
*/
class SALNotNull extends SALAnnotation {
SALNotNull() {
exists(SALMacro m | m = this.getMacro() |
class SalNotNull extends SalAnnotation {
SalNotNull() {
exists(SalMacro m | m = this.getMacro() |
not m.getName().matches("%\\_opt\\_%") and
(
m.getName().matches("_In%") or
@@ -80,12 +89,15 @@ class SALNotNull extends SALAnnotation {
}
}
/** DEPRECATED: Alias for SalNotNull */
deprecated class SALNotNull = SalNotNull;
/**
* A SAL macro indicating that a value may be `NULL`.
*/
class SALMaybeNull extends SALAnnotation {
SALMaybeNull() {
exists(SALMacro m | m = this.getMacro() |
class SalMaybeNull extends SalAnnotation {
SalMaybeNull() {
exists(SalMacro m | m = this.getMacro() |
m.getName().matches("%\\_opt\\_%") or
m.getName().matches("\\_Ret_maybenull\\_%") or
m.getName() = "_Result_nullonfailure_"
@@ -93,14 +105,17 @@ class SALMaybeNull extends SALAnnotation {
}
}
/** DEPRECATED: Alias for SalMaybeNull */
deprecated class SALMaybeNull = SalMaybeNull;
/**
* A parameter annotated by one or more SAL annotations.
*/
class SALParameter extends Parameter {
class SalParameter extends Parameter {
/** One of this parameter's annotations. */
SALAnnotation a;
SalAnnotation a;
SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) }
SalParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) }
predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") }
@@ -109,14 +124,17 @@ class SALParameter extends Parameter {
predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") }
}
/** DEPRECATED: Alias for SalParameter */
deprecated class SALParameter = SalParameter;
///////////////////////////////////////////////////////////////////////////////
// Implementation details
/**
* Holds if `a` annotates the declaration entry `d` and
* its start position is the `idx`th position in `file` that holds a SAL element.
*/
private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) {
annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx)
private predicate annotatesAt(SalAnnotation a, DeclarationEntry d, File file, int idx) {
annotatesAtPosition(a.(SalElement).getStartPosition(), d, file, idx)
}
/**
@@ -127,12 +145,12 @@ private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, in
// For performance reasons, do not mention the annotation itself here,
// but compute with positions instead. This performs better on databases
// with many annotations at the same position.
private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File file, int idx) {
private predicate annotatesAtPosition(SalPosition pos, DeclarationEntry d, File file, int idx) {
pos = salRelevantPositionAt(file, idx) and
salAnnotationPos(pos) and
(
// Base case: `pos` right before `d`
d.(SALElement).getStartPosition() = salRelevantPositionAt(file, idx + 1)
d.(SalElement).getStartPosition() = salRelevantPositionAt(file, idx + 1)
or
// Recursive case: `pos` right before some annotation on `d`
annotatesAtPosition(_, d, file, idx + 1)
@@ -143,10 +161,10 @@ private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File
* A SAL element, that is, a SAL annotation or a declaration entry
* that may have SAL annotations.
*/
library class SALElement extends Element {
SALElement() {
containsSALAnnotation(this.(DeclarationEntry).getFile()) or
this instanceof SALAnnotation
library class SalElement extends Element {
SalElement() {
containsSalAnnotation(this.(DeclarationEntry).getFile()) or
this instanceof SalAnnotation
}
predicate hasStartPosition(File file, int line, int col) {
@@ -173,25 +191,28 @@ library class SALElement extends Element {
)
}
SALPosition getStartPosition() {
SalPosition getStartPosition() {
exists(File file, int line, int col |
this.hasStartPosition(file, line, col) and
result = MkSALPosition(file, line, col)
result = MkSalPosition(file, line, col)
)
}
}
/** DEPRECATED: Alias for SalElement */
deprecated class SALElement = SalElement;
/** Holds if `file` contains a SAL annotation. */
pragma[noinline]
private predicate containsSALAnnotation(File file) { any(SALAnnotation a).getFile() = file }
private predicate containsSalAnnotation(File file) { any(SalAnnotation a).getFile() = file }
/**
* A source-file position of a `SALElement`. Unlike location, this denotes a
* point in the file rather than a range.
*/
private newtype SALPosition =
MkSALPosition(File file, int line, int col) {
exists(SALElement e |
private newtype SalPosition =
MkSalPosition(File file, int line, int col) {
exists(SalElement e |
e.hasStartPosition(file, line, col)
or
e.hasEndPosition(file, line, col)
@@ -200,18 +221,18 @@ private newtype SALPosition =
/** Holds if `pos` is the start position of a SAL annotation. */
pragma[noinline]
private predicate salAnnotationPos(SALPosition pos) {
any(SALAnnotation a).(SALElement).getStartPosition() = pos
private predicate salAnnotationPos(SalPosition pos) {
any(SalAnnotation a).(SalElement).getStartPosition() = pos
}
/**
* Gets the `idx`th position in `file` that holds a SAL element,
* ordering positions lexicographically by their start line and start column.
*/
private SALPosition salRelevantPositionAt(File file, int idx) {
private SalPosition salRelevantPositionAt(File file, int idx) {
result =
rank[idx](SALPosition pos, int line, int col |
pos = MkSALPosition(file, line, col)
rank[idx](SalPosition pos, int line, int col |
pos = MkSalPosition(file, line, col)
|
pos order by line, col
)

View File

@@ -24,7 +24,7 @@ where
if e = DefinitionInSnapshot()
then defined = ""
else
if e = SuggestiveSALAnnotation()
if e = SuggestiveSalAnnotation()
then defined = "externally defined (SAL) "
else defined = "externally defined (CSV) "
)

View File

@@ -149,7 +149,7 @@ newtype Evidence =
* The function is externally defined, but the parameter has an `_out` SAL annotation which
* suggests that it is initialized in the function.
*/
SuggestiveSALAnnotation() or
SuggestiveSalAnnotation() or
/**
* We have been given a CSV file which indicates this parameter is conditionally initialized.
*/
@@ -198,8 +198,8 @@ class InitializationFunction extends Function {
or
// If we have no definition, we look at SAL annotations
not this.hasDefinition() and
this.getParameter(i).(SALParameter).isOut() and
evidence = SuggestiveSALAnnotation()
this.getParameter(i).(SalParameter).isOut() and
evidence = SuggestiveSalAnnotation()
or
// We have some external information that this function conditionally initializes
not this.hasDefinition() and

View File

@@ -19,8 +19,8 @@ import DataFlow::PathGraph
/**
* A configuration for tracking XML objects and their states.
*/
class XXEConfiguration extends DataFlow::Configuration {
XXEConfiguration() { this = "XXEConfiguration" }
class XxeConfiguration extends DataFlow::Configuration {
XxeConfiguration() { this = "XXEConfiguration" }
override predicate isSource(DataFlow::Node node, string flowstate) {
any(XmlLibrary l).configurationSource(node, flowstate)
@@ -45,7 +45,7 @@ class XXEConfiguration extends DataFlow::Configuration {
}
}
from XXEConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink
from XxeConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink
where conf.hasFlowPath(source, sink)
select sink, source, sink,
"This $@ is not configured to prevent an XML external entity (XXE) attack.", source, "XML parser"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The alert message of many queries have been changed to make the message consistent with other languages.

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new medium-precision query, `cpp/missing-check-scanf`, which detects `scanf` output variables that are used without a proper return-value check to see that they were actually written. A variation of this query was originally contributed as an [experimental query by @ihsinme](https://github.com/github/codeql/pull/8246).

View File

@@ -1 +0,0 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.4
lastReleaseVersion: 0.3.3

View File

@@ -16,17 +16,17 @@ import cpp
// pointers. This will obviously not catch code that uses inline assembly to achieve
// self-modification, nor will it spot the use of OS mechanisms to write into process
// memory (such as WriteProcessMemory under Windows).
predicate maybeSMCConversion(Type t1, Type t2) {
predicate maybeSmcConversion(Type t1, Type t2) {
t1 instanceof FunctionPointerType and
t2 instanceof PointerType and
not t2 instanceof FunctionPointerType and
not t2 instanceof VoidPointerType
or
maybeSMCConversion(t2, t1)
maybeSmcConversion(t2, t1)
}
from Expr e
where
e.fromSource() and
maybeSMCConversion(e.getUnderlyingType(), e.getActualType())
maybeSmcConversion(e.getUnderlyingType(), e.getActualType())
select e, "AV Rule 2: There shall not be any self-modifying code."

View File

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

View File

@@ -1,5 +1,5 @@
import cpp
from Class c, boolean ispod
where if c.isPOD() then ispod = true else ispod = false
where if c.isPod() then ispod = true else ispod = false
select c, ispod

View File

@@ -1,5 +1,5 @@
import semmle.code.cpp.PODType03
from Class c, boolean ispod
where if isPODClass03(c) then ispod = true else ispod = false
where if isPodClass03(c) then ispod = true else ispod = false
select c, ispod

View File

@@ -1,4 +1,4 @@
import Microsoft.SAL
from SALAnnotation a
from SalAnnotation a
select a, a.getDeclaration()

View File

@@ -1,3 +1,3 @@
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment |
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment |
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment |
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment. |
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment. |
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment. |

View File

@@ -0,0 +1,19 @@
| test.cpp:30:7:30:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:30:7:30:7 | i | i | test.cpp:29:3:29:7 | call to scanf | call to scanf |
| test.cpp:46:7:46:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:46:7:46:7 | i | i | test.cpp:45:3:45:7 | call to scanf | call to scanf |
| test.cpp:63:7:63:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:63:7:63:7 | i | i | test.cpp:62:3:62:7 | call to scanf | call to scanf |
| test.cpp:75:7:75:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:75:7:75:7 | i | i | test.cpp:74:3:74:7 | call to scanf | call to scanf |
| test.cpp:87:7:87:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:87:7:87:7 | i | i | test.cpp:86:3:86:8 | call to fscanf | call to fscanf |
| test.cpp:94:7:94:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:94:7:94:7 | i | i | test.cpp:93:3:93:8 | call to sscanf | call to sscanf |
| test.cpp:143:8:143:8 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:143:8:143:8 | i | i | test.cpp:141:7:141:11 | call to scanf | call to scanf |
| test.cpp:152:8:152:8 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:152:8:152:8 | i | i | test.cpp:150:7:150:11 | call to scanf | call to scanf |
| test.cpp:184:8:184:8 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:184:8:184:8 | i | i | test.cpp:183:7:183:11 | call to scanf | call to scanf |
| test.cpp:203:8:203:8 | j | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:203:8:203:8 | j | j | test.cpp:200:7:200:11 | call to scanf | call to scanf |
| test.cpp:227:9:227:9 | d | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:227:9:227:9 | d | d | test.cpp:225:25:225:29 | call to scanf | call to scanf |
| test.cpp:231:9:231:9 | d | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:231:9:231:9 | d | d | test.cpp:229:14:229:18 | call to scanf | call to scanf |
| test.cpp:243:7:243:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:243:7:243:7 | i | i | test.cpp:242:3:242:7 | call to scanf | call to scanf |
| test.cpp:251:7:251:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:251:7:251:7 | i | i | test.cpp:250:3:250:7 | call to scanf | call to scanf |
| test.cpp:259:7:259:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:259:7:259:7 | i | i | test.cpp:258:3:258:7 | call to scanf | call to scanf |
| test.cpp:271:7:271:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:271:7:271:7 | i | i | test.cpp:270:3:270:7 | call to scanf | call to scanf |
| test.cpp:281:8:281:12 | ptr_i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:281:8:281:12 | ptr_i | ptr_i | test.cpp:280:3:280:7 | call to scanf | call to scanf |
| test.cpp:289:7:289:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:289:7:289:7 | i | i | test.cpp:288:3:288:7 | call to scanf | call to scanf |
| test.cpp:383:25:383:25 | u | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:383:25:383:25 | u | u | test.cpp:382:6:382:11 | call to sscanf | call to sscanf |

View File

@@ -0,0 +1 @@
Critical/MissingCheckScanf.ql

View File

@@ -0,0 +1,387 @@
typedef struct
{
} FILE;
typedef void *locale_t;
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *s, const char *format, ...);
int _scanf_l(const char *format, locale_t locale, ...);
void use(int i);
void set_by_ref(int &i);
void set_by_ptr(int *i);
bool maybe();
FILE *get_a_stream();
const char *get_a_string();
extern locale_t get_a_locale();
int main()
{
// --- simple cases ---
{
int i;
scanf("%d", &i);
use(i); // BAD: may not have written `i`
}
{
int i;
if (scanf("%d", &i) == 1)
{
use(i); // GOOD: checks return value
}
}
{
int i = 0;
scanf("%d", &i);
use(i); // BAD. Design choice: already initialized variables shouldn't make a difference.
}
{
int i;
use(i); // GOOD: only care about uses after scanf call
if (scanf("%d", &i) == 1)
{
use(i); // GOOD
}
}
{
int i; // Reused variable
scanf("%d", &i);
use(i); // BAD
if (scanf("%d", &i) == 1)
{
use(i); // GOOD
}
}
{
int i; // Reset variable
scanf("%d", &i);
use(i); // BAD
i = 1;
use(i); // GOOD
}
// --- different scanf functions ---
{
int i;
fscanf(get_a_stream(), "%d", &i);
use(i); // BAD: may not have written `i`
}
{
int i;
sscanf(get_a_string(), "%d", &i);
use(i); // BAD: may not have written `i`
}
{
int i;
if (_scanf_l("%d", get_a_locale(), &i) == 1)
{
use(i); // GOOD
}
}
// --- different ways of checking ---
{
int i;
if (scanf("%d", &i) >= 1)
{
use(i); // GOOD
}
}
{
int i;
if (scanf("%d", &i) == 1)
{
use(i); // GOOD
}
}
{
int i;
if (0 < scanf("%d", &i))
{
if (true)
{
use(i); // GOOD
}
}
}
{
int i;
if (scanf("%d", &i) != 0)
{
use(i); // BAD: scanf can return EOF
}
}
{
int i;
if (scanf("%d", &i) == 0)
{
use(i); // BAD: checks return value incorrectly
}
}
{
int r;
int i;
r = scanf("%d", &i);
if (r >= 1)
{
use(i); // GOOD
}
}
{
bool b;
int i;
b = scanf("%d", &i);
if (b >= 1)
{
use(i); // BAD [NOT DETECTED]: scanf can return EOF (boolifies true)
}
}
{
int i;
if (scanf("%d", &i))
use(i); // BAD
}
{
int i, j;
if (scanf("%d %d", &i) >= 2)
{
use(i); // GOOD
use(j); // GOOD: `j` is not a scanf arg, so out of scope of MissingCheckScanf
}
}
{
int i, j;
if (scanf("%d %d", &i, &j) >= 1)
{
use(i); // GOOD
use(j); // BAD: checks return value incorrectly
}
}
{
int i, j;
if (scanf("%d %d", &i, &j) >= 2)
{
use(i); // GOOD
use(j); // GOOD
}
}
{
char c[5];
int d;
while(maybe()) {
if (maybe()) {
break;
}
else if (maybe() && (scanf("%5c %d", c, &d) == 1)) { // GOOD
use(*(int *)c); // GOOD
use(d); // BAD
}
else if ((scanf("%5c %d", c, &d) == 1) && maybe()) { // GOOD
use(*(int *)c); // GOOD
use(d); // BAD
}
}
}
// --- different initialization ---
{
int i;
i = 0;
scanf("%d", &i);
use(i); // BAD
}
{
int i;
set_by_ref(i);
scanf("%d", &i);
use(i); // BAD
}
{
int i;
set_by_ptr(&i);
scanf("%d", &i);
use(i); // BAD
}
{
int i;
if (maybe())
{
i = 0;
}
scanf("%d", &i);
use(i); // BAD: `i` may not have been initialized
}
// --- different use ---
{
int i;
int *ptr_i = &i;
scanf("%d", &i);
use(*ptr_i); // BAD: may not have written `i`
}
{
int i;
int *ptr_i = &i;
scanf("%d", ptr_i);
use(i); // BAD: may not have written `*ptr_i`
}
{
int i;
scanf("%d", &i);
i = 42;
use(i); // GOOD
}
// --- weird formatting strings ---
{
int i, j;
if (sscanf("123", "%n %*d %n", &i, &j) >= 0)
{
use(i); // GOOD (`%n` does not consume input, but writes 0 to i)
use(j); // GOOD (`%n` does not consume input, but writes 3 to j)
}
}
{
int i;
if (scanf("%% %d", &i) >= 1)
{
use(i); // GOOD (`%%` does not consume input)
}
}
{
int i;
if (scanf("%*d %d", &i) >= 1)
{
use(i); // GOOD (`%*d` does not consume input)
}
}
{
int d, n;
if (scanf("%*d %d %n", &d, &n) == 1) {
use(d); // GOOD
use(n); // GOOD
}
}
{
char substr[32];
int n;
while (sscanf(get_a_string(), "%31[^:]: %d", substr, &n) == 2) { // GOOD: cycle from write to unguarded access
use(*(int *)substr); // GOOD
use(n); // GOOD
}
}
}
// --- Non-local cases ---
bool my_scan_int(int &i)
{
return scanf("%d", &i) == 1; // GOOD
}
void my_scan_int_test()
{
int i;
use(i); // GOOD: used before scanf
my_scan_int(i);
use(i); // BAD [NOT DETECTED]
if (my_scan_int(i))
{
use(i); // GOOD
}
}
// --- Can be OK'd given a sufficiently smart analysis ---
char *my_string_copy() {
static const char SRC_STRING[] = "48656C6C6F";
static char DST_STRING[] = ".....";
int len = sizeof(SRC_STRING) - 1;
const char *src = SRC_STRING;
char *ptr = DST_STRING;
for (int i = 0; i < len; i += 2) {
unsigned int u;
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u; // GOOD [FALSE POSITIVE]? src+i+{0,1} are always valid %x digits, so this should be OK.
}
*ptr++ = 0;
return DST_STRING;
}

View File

@@ -1,20 +1,20 @@
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code |
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code |
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code |
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code |
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code |
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code |
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code |
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code |
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code |
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code |
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code |
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code |
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code |
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code |
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code |
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code |
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code |
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code |
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code |
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code |
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code. |
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code. |
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code. |
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code. |
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code. |
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code. |
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code. |
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code. |
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code. |
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code. |
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code. |
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code. |
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code. |
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code. |
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code. |

View File

@@ -1,4 +1,4 @@
| bsc.cpp:2:10:2:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:6:10:6:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:18:10:18:28 | ... > ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:22:10:22:28 | ... < ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:2:10:2:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:6:10:6:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:18:10:18:28 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:22:10:22:28 | ... < ... | Potentially unsafe sign check of a bitwise operation. |

View File

@@ -1,4 +1,4 @@
| c.c:10:5:10:10 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:14:5:14:14 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:16:5:16:12 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:17:5:17:12 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:10:5:10:10 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:14:5:14:14 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:16:5:16:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:17:5:17:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |

View File

@@ -64,10 +64,6 @@ edges
| test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 |
| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p |
| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 |
| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p |
#select
| test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
| test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
@@ -94,5 +90,3 @@ edges
| test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
| test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
| test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here |
| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here |

View File

@@ -209,61 +209,4 @@ int maybe_deref_p(bool b) {
int field_indirect_maybe_bad(bool b) {
escape1();
return maybe_deref_p(b);
}
// These next tests cover subsequent stores to the same address in the same basic block.
static struct S100 s102;
void not_escape1() {
int x;
s102.p = &x;
s102.p = nullptr;
}
void calls_not_escape1() {
not_escape1();
int x = *s102.p; // GOOD
}
static struct S100 s103;
void escape2() {
int x;
s103.p = nullptr;
s103.p = &x;
}
void calls_escape2() {
escape2();
int x = *s103.p; // BAD
}
bool unknown();
static struct S100 s104;
void not_escape2() {
int x;
s104.p = &x;
if(unknown()) { }
s104.p = nullptr;
}
void calls_not_escape2() {
not_escape2();
int x = *s104.p; // GOOD
}
static struct S100 s105;
void escape3() {
int x;
s105.p = nullptr;
if(unknown()) { }
s105.p = &x;
}
void calls_escape3() {
escape3();
int x = *s105.p; // BAD
}

View File

@@ -413,7 +413,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["cmd.exe /C dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet restore C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet build --no-incremental C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -440,7 +440,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -715,9 +715,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuild()
{
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test2.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -746,9 +746,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildMultipleSolutions()
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test2.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test1.csproj"] = true;
actions.FileExists[@"C:\Project\test2.csproj"] = true;
@@ -791,7 +791,7 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildFailed()
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 1;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 1;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -817,8 +817,8 @@ namespace Semmle.Autobuild.CSharp.Tests
[Fact]
public void TestSkipNugetMsBuild()
{
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -862,7 +862,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental /p:UseSharedCompilation=false --no-restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental --no-restore C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -894,7 +894,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -929,7 +929,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -960,7 +960,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet build --no-incremental C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -1008,7 +1008,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\a\test.csproj"] = true;
actions.FileExists[@"C:\Project\dirs.proj"] = true;
@@ -1052,7 +1052,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"nuget restore C:\Project/dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"mono C:\Project/.nuget/nuget.exe restore C:\Project/dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess[@"msbuild C:\Project/dirs.proj /p:UseSharedCompilation=false /t:rebuild /p:MvcBuildViews=true"] = 0;
actions.RunProcess[@"msbuild C:\Project/dirs.proj /t:rebuild"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/a/test.csproj"] = true;
actions.FileExists[@"C:\Project/dirs.proj"] = true;

View File

@@ -5,7 +5,6 @@ using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using Semmle.Util;
using System.Text.RegularExpressions;
using Semmle.Autobuild.Shared;
namespace Semmle.Autobuild.CSharp
@@ -81,9 +80,6 @@ namespace Semmle.Autobuild.CSharp
env = null;
}
if (env is null)
env = new Dictionary<string, string>();
env.Add("UseSharedCompilation", "false");
return f(installDir, env);
});
}
@@ -245,8 +241,7 @@ namespace Semmle.Autobuild.CSharp
Argument("--no-incremental");
return
script.Argument("/p:UseSharedCompilation=false").
Argument(builder.Options.DotNetArguments).
script.Argument(builder.Options.DotNetArguments).
QuoteArgument(projOrSln).
Script;
}

View File

@@ -98,8 +98,6 @@ namespace Semmle.Autobuild.Shared
command.RunCommand(msBuild);
command.QuoteArgument(projectOrSolution.FullPath);
command.Argument("/p:UseSharedCompilation=false");
var target = builder.Options.MsBuildTarget ?? "rebuild";
var platform = builder.Options.MsBuildPlatform ?? (projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null);
var configuration = builder.Options.MsBuildConfiguration ?? (projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null);
@@ -109,7 +107,6 @@ namespace Semmle.Autobuild.Shared
command.Argument(string.Format("/p:Platform=\"{0}\"", platform));
if (configuration is not null)
command.Argument(string.Format("/p:Configuration=\"{0}\"", configuration));
command.Argument("/p:MvcBuildViews=true");
command.Argument(builder.Options.MsBuildArguments);

View File

@@ -35,3 +35,10 @@ options:
the code (for example if it uses inaccessible dependencies).
type: string
pattern: "^(false|true)$"
cil:
title: Whether to enable CIL extraction.
description: >
A value indicating, whether CIL extraction should be enabled.
The default is 'true'.
type: string
pattern: "^(false|true)$"

View File

@@ -9,7 +9,7 @@ Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,45,1
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,80,3
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,62,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,12,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,15,
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,16,
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,13,2
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,16,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,10,
@@ -24,5 +24,5 @@ Microsoft.Win32,,,8,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,,75,92,,,,7,
System,43,4,11809,,1,1,1,,4,,33,3,1,3,9867,1942
System,65,4,12081,,8,8,9,,4,,33,3,1,3,10139,1942
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,
1 package sink source summary sink:code sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:html sink:remote sink:sql sink:xss source:file source:local summary:taint summary:value
9 Microsoft.Extensions.Configuration 83 80 3
10 Microsoft.Extensions.DependencyInjection 62 62
11 Microsoft.Extensions.DependencyModel 12 12
12 Microsoft.Extensions.FileProviders 15 16 15 16
13 Microsoft.Extensions.FileSystemGlobbing 15 13 2
14 Microsoft.Extensions.Hosting 17 16 1
15 Microsoft.Extensions.Http 10 10
24 MySql.Data.MySqlClient 48 48
25 Newtonsoft.Json 91 73 18
26 ServiceStack 194 7 27 75 92 7
27 System 43 65 4 11809 12081 1 8 1 8 1 9 4 33 3 1 3 9867 10139 1942
28 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",4,11809,43,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,554,138,
Totals,,4,12370,375,7
System,"``System.*``, ``System``",4,12081,65,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,555,138,
Totals,,4,12643,397,7

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Introduce '--cil' flag in the comments. This does not make any changes to the dbscheme.
compatibility: full

View File

@@ -13,31 +13,6 @@ namespace Semmle.Extraction.CSharp
{
Extractor.SetInvariantCulture();
Console.WriteLine($"Semmle.Extraction.CSharp.Driver: called with {string.Join(", ", args)}");
if (args.Length > 0 && args[0] == "--dotnetexec")
{
var compilerRegEx = new Regex(@"csc\.exe|mcs\.exe|csc\.dll", RegexOptions.Compiled);
var cil = args.Length > 1 && args[1] == "--cil";
for (var i = cil ? 2 : 1; i < args.Length; i++)
{
if (compilerRegEx.IsMatch(args[i]))
{
var argsList = new List<string>();
if (cil)
argsList.Add("--cil");
argsList.Add("--compiler");
argsList.Add(args[i]);
if (i + 1 < args.Length)
argsList.AddRange(args[(i + 1)..]);
return (int)Extractor.Run(argsList.ToArray());
}
}
Console.WriteLine($"Semmle.Extraction.CSharp.Driver: not a compiler invocation");
return 0;
}
return (int)Extractor.Run(args);
}
}

View File

@@ -56,7 +56,6 @@ namespace Semmle.Extraction.CSharp.Standalone
CSharp.Extractor.SetInvariantCulture();
var options = Options.Create(args);
// options.CIL = true; // To do: Enable this
if (options.Help)
{

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.Tests
{
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.Cache);
Assert.False(options.CIL);
Assert.True(options.CIL);
Assert.Null(options.Framework);
Assert.Null(options.CompilerName);
Assert.Empty(options.CompilerArguments);
@@ -51,10 +51,20 @@ namespace Semmle.Extraction.Tests
[Fact]
public void CIL()
{
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil" });
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil", "--nocil" });
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "false");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.False(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "true");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", null);
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
}
[Fact]
@@ -121,22 +131,6 @@ namespace Semmle.Extraction.Tests
Assert.Equal("foo", options.Framework);
}
[Fact]
public void EnvironmentVariables()
{
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "--cil c");
options = CSharp.Options.CreateWithEnvironment(new string[] { "a", "b" });
Assert.True(options.CIL);
Assert.Equal("a", options.CompilerArguments[0]);
Assert.Equal("b", options.CompilerArguments[1]);
Assert.Equal("c", options.CompilerArguments[2]);
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "");
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "--nocil");
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil" });
Assert.False(options.CIL);
}
[Fact]
public void StandaloneDefaults()
{

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction
/// <summary>
/// Holds if CIL should be extracted.
/// </summary>
public bool CIL { get; private set; } = false;
public bool CIL { get; private set; } = true;
/// <summary>
/// Holds if assemblies shouldn't be extracted twice.
@@ -50,7 +50,6 @@ namespace Semmle.Extraction
/// </summary>
public bool QlTest { get; private set; } = false;
/// <summary>
/// The compression algorithm used for trap files.
/// </summary>
@@ -73,6 +72,9 @@ namespace Semmle.Extraction
return true;
}
return false;
case "cil":
CIL = Boolean.Parse(value);
return true;
default:
return false;
}
@@ -97,9 +99,6 @@ namespace Semmle.Extraction
case "cache":
Cache = value;
return true;
case "cil":
CIL = value;
return true;
case "pdb":
PDB = value;
CIL = true;

View File

@@ -17,7 +17,7 @@ namespace Semmle.Util
bool HandleOption(string key, string value);
/// <summary>
/// Handle a flag of the form "--cil" or "--nocil"
/// Handle a flag of the form "--cache" or "--nocache"
/// </summary>
/// <param name="key">The name of the flag. This is case sensitive.</param>
/// <param name="value">True if set, or false if prefixed by "--no"</param>
@@ -40,6 +40,7 @@ namespace Semmle.Util
public static class OptionsExtensions
{
private static readonly string[] ExtractorOptions = new[] { "trap_compression", "cil" };
private static string? GetExtractorOption(string name) =>
Environment.GetEnvironmentVariable($"CODEQL_EXTRACTOR_CSHARP_OPTION_{name.ToUpper()}");
@@ -47,12 +48,14 @@ namespace Semmle.Util
{
var extractorOptions = new List<string>();
var trapCompression = GetExtractorOption("trap_compression");
if (!string.IsNullOrEmpty(trapCompression))
foreach (var option in ExtractorOptions)
{
extractorOptions.Add($"--trap_compression:{trapCompression}");
var value = GetExtractorOption(option);
if (!string.IsNullOrEmpty(value))
{
extractorOptions.Add($"--{option}:{value}");
}
}
return extractorOptions;
}

View File

@@ -1,5 +1,3 @@
## 1.2.5
## 1.2.4
## 1.2.3

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.5
lastReleaseVersion: 1.2.4

View File

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

View File

@@ -1,5 +1,3 @@
## 1.2.5
## 1.2.4
## 1.2.3

View File

@@ -15,7 +15,7 @@ import experimental.code.csharp.Cryptography.NonCryptographicHashes
from Variable v, Literal l, LoopStmt loop, Expr additional_xor
where
maybeUsedInFNVFunction(v, _, _, loop) and
maybeUsedInFnvFunction(v, _, _, loop) and
(
exists(BitwiseXorExpr xor2 | xor2.getAnOperand() = l and additional_xor = xor2 |
loop.getAControlFlowExitNode().getASuccessor*() = xor2.getAControlFlowNode() and

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.5
lastReleaseVersion: 1.2.4

View File

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

View File

@@ -1,8 +1,8 @@
import csharp
import semmle.code.csharp.dataflow.internal.SsaImplCommon::Consistency
import semmle.code.csharp.dataflow.internal.SsaImpl::Consistency as Consistency
import Ssa
class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
class MyRelevantDefinition extends Consistency::RelevantDefinition, Ssa::Definition {
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
@@ -10,6 +10,14 @@ class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
}
}
query predicate nonUniqueDef = Consistency::nonUniqueDef/4;
query predicate readWithoutDef = Consistency::readWithoutDef/3;
query predicate deadDef = Consistency::deadDef/2;
query predicate notDominatedByDef = Consistency::notDominatedByDef/4;
query predicate localDeclWithSsaDef(LocalVariableDeclExpr d) {
// Local variables in C# must be initialized before every use, so uninitialized
// local variables should not have an SSA definition, as that would imply that

View File

@@ -1,5 +1,3 @@
## 0.3.5
## 0.3.4
### Deprecated APIs

View File

@@ -1 +0,0 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.5
lastReleaseVersion: 0.3.4

View File

@@ -13,7 +13,7 @@ private import semmle.code.csharp.dataflow.TaintTracking2
predicate maybeANonCryptogrphicHash(Callable callable, Variable v, Expr xor, Expr mul, LoopStmt loop) {
callable = loop.getEnclosingCallable() and
(
maybeUsedInFNVFunction(v, xor, mul, loop) or
maybeUsedInFnvFunction(v, xor, mul, loop) or
maybeUsedInElfHashFunction(v, xor, mul, loop)
)
}
@@ -23,7 +23,7 @@ predicate maybeANonCryptogrphicHash(Callable callable, Variable v, Expr xor, Exp
* where there is a loop statement `loop` where the variable `v` is used in an xor `xor` expression
* followed by a multiplication `mul` expression.
*/
predicate maybeUsedInFNVFunction(Variable v, Operation xor, Operation mul, LoopStmt loop) {
predicate maybeUsedInFnvFunction(Variable v, Operation xor, Operation mul, LoopStmt loop) {
exists(Expr e1, Expr e2 |
e1.getAChild*() = v.getAnAccess() and
e2.getAChild*() = v.getAnAccess() and
@@ -37,6 +37,9 @@ predicate maybeUsedInFNVFunction(Variable v, Operation xor, Operation mul, LoopS
loop.getAChild*() = xor.getEnclosingStmt()
}
/** DEPRECATED: Alias for maybeUsedInFnvFunction */
deprecated predicate maybeUsedInFNVFunction = maybeUsedInFnvFunction/4;
/**
* Holds if the arguments are used in a way that resembles an Elf-Hash hash function
* where there is a loop statement `loop` where the variable `v` is used in an xor `xor` expression

View File

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

View File

@@ -8,13 +8,12 @@ private import CIL
* Provides classes for working with static single assignment (SSA) form.
*/
module Ssa {
private import internal.SsaImplCommon as SsaImpl
private import internal.SsaImpl
private import internal.SsaImpl as SsaImpl
/** An SSA definition. */
class Definition extends SsaImpl::Definition {
/** Gets a read of this SSA definition. */
final ReadAccess getARead() { result = getARead(this) }
final ReadAccess getARead() { result = SsaImpl::getARead(this) }
/** Gets the underlying variable update, if any. */
final VariableUpdate getVariableUpdate() {
@@ -25,11 +24,11 @@ module Ssa {
}
/** Gets a first read of this SSA definition. */
final ReadAccess getAFirstRead() { result = getAFirstRead(this) }
final ReadAccess getAFirstRead() { result = SsaImpl::getAFirstRead(this) }
/** Holds if `first` and `second` are adjacent reads of this SSA definition. */
final predicate hasAdjacentReads(ReadAccess first, ReadAccess second) {
hasAdjacentReads(this, first, second)
SsaImpl::hasAdjacentReads(this, first, second)
}
private Definition getAPhiInput() { result = this.(PhiNode).getAnInput() }
@@ -52,7 +51,7 @@ module Ssa {
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
/** Gets an input to this phi node. */
final Definition getAnInput() { result = getAPhiInput(this) }
final Definition getAnInput() { result = SsaImpl::getAPhiInput(this) }
/**
* Holds if if `def` is an input to this phi node, and a reference to `def` at
@@ -60,7 +59,7 @@ module Ssa {
* other references.
*/
final predicate hasLastInputRef(Definition def, BasicBlock bb, int i) {
hasLastInputRef(this, def, bb, i)
SsaImpl::hasLastInputRef(this, def, bb, i)
}
}
}

View File

@@ -1,8 +1,40 @@
private import semmle.code.cil.CIL
private import SsaImplCommon
private import cil
private import semmle.code.csharp.dataflow.internal.SsaImplCommon as SsaImplCommon
private module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = CIL::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = CIL::ExitBasicBlock;
class SourceVariable = CIL::StackVariable;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
forceCachingInSameStage() and
exists(CIL::VariableUpdate vu |
vu.updatesAt(bb, i) and
v = vu.getVariable() and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(CIL::ReadAccess ra | bb.getNode(i) = ra |
ra.getTarget() = v and
certain = true
)
}
}
import SsaImplCommon::Make<SsaInput>
cached
private module Cached {
private import CIL
cached
predicate forceCachingInSameStage() { any() }

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,30 +0,0 @@
/** Provides the CIL specific parameters for `SsaImplCommon.qll`. */
private import cil
private import SsaImpl
class BasicBlock = CIL::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = CIL::ExitBasicBlock;
class SourceVariable = CIL::StackVariable;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
forceCachingInSameStage() and
exists(CIL::VariableUpdate vu |
vu.updatesAt(bb, i) and
v = vu.getVariable() and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(CIL::ReadAccess ra | bb.getNode(i) = ra |
ra.getTarget() = v and
certain = true
)
}

View File

@@ -192,8 +192,7 @@ class BasicBlock extends TBasicBlockStart {
* Gets the basic block that immediately dominates this basic block, if any.
*
* That is, all paths reaching this basic block from some entry point
* basic block must go through the result, which is an immediate basic block
* predecessor of this basic block.
* basic block must go through the result.
*
* Example:
*
@@ -207,8 +206,7 @@ class BasicBlock extends TBasicBlockStart {
*
* The basic block starting on line 2 is an immediate dominator of
* the basic block online 4 (all paths from the entry point of `M`
* to `return s.Length;` must go through the null check, and the null check
* is an immediate predecessor of `return s.Length;`).
* to `return s.Length;` must go through the null check.
*/
BasicBlock getImmediateDominator() { bbIDominates(result, this) }

View File

@@ -6,26 +6,158 @@ import csharp
* scope variables.
*/
module PreSsa {
import pressa.SsaImplSpecific
private import pressa.SsaImplCommon as SsaImpl
private import AssignableDefinitions
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.internal.PreBasicBlocks as PreBasicBlocks
private import semmle.code.csharp.dataflow.internal.SsaImplCommon as SsaImplCommon
private predicate definitionAt(
AssignableDefinition def, SsaInput::BasicBlock bb, int i, SsaInput::SourceVariable v
) {
bb.getElement(i) = def.getExpr() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
or
def.(ImplicitParameterDefinition).getParameter() = v and
exists(Callable c | v = c.getAParameter() |
scopeFirst(c, bb) and
i = -1
)
}
predicate implicitEntryDef(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v) {
not v instanceof LocalScopeVariable and
c = v.getACallable() and
scopeFirst(c, bb)
}
module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = PreBasicBlocks::PreBasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { scopeLast(_, this.getLastElement(), _) }
}
/** Holds if `a` is assigned in non-constructor callable `c`. */
pragma[nomagic]
private predicate assignableDefinition(Assignable a, Callable c) {
exists(AssignableDefinition def | def.getTarget() = a |
c = def.getEnclosingCallable() and
not c instanceof Constructor
)
}
/** Holds if `a` is accessed in callable `c`. */
pragma[nomagic]
private predicate assignableAccess(Assignable a, Callable c) {
exists(AssignableAccess aa | aa.getTarget() = a | c = aa.getEnclosingCallable())
}
pragma[nomagic]
private predicate assignableNoCapturing(Assignable a, Callable c) {
assignableAccess(a, c) and
/*
* The code below is equivalent to
* ```ql
* not exists(Callable other | assignableDefinition(a, other) | other != c)
* ```
* but it avoids a Cartesian product in the compiler generated antijoin
* predicate.
*/
(
not assignableDefinition(a, _)
or
c = unique(Callable c0 | assignableDefinition(a, c0) | c0)
)
}
pragma[noinline]
private predicate assignableNoComplexQualifiers(Assignable a) {
forall(QualifiableExpr qe | qe.(AssignableAccess).getTarget() = a | qe.targetIsThisInstance())
}
/**
* A simple assignable. Either a local scope variable or a field/property
* that behaves like a local scope variable.
*/
class SourceVariable extends Assignable {
private Callable c;
SourceVariable() {
(
this instanceof LocalScopeVariable
or
this = any(Field f | not f.isVolatile())
or
this = any(TrivialProperty tp | not tp.isOverridableOrImplementable())
) and
assignableNoCapturing(this, c) and
assignableNoComplexQualifiers(this)
}
/** Gets a callable in which this simple assignable can be analyzed. */
Callable getACallable() { result = c }
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.getTargetAccess().isRefArgument() then certain = false else certain = true
)
or
exists(Callable c |
implicitEntryDef(c, bb, v) and
i = -1 and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read = bb.getElement(i) and
read.getTarget() = v and
certain = true
)
or
v =
any(LocalScopeVariable lsv |
lsv.getCallable() = bb.(ExitBasicBlock).getEnclosingCallable() and
i = bb.length() and
(lsv.isRef() or v.(Parameter).isOut()) and
certain = false
)
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {
exists(BasicBlock bb, int i |
exists(SsaInput::BasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(_, this, bb, i) and
result = bb.getElement(i)
)
}
final AssignableDefinition getDefinition() {
exists(BasicBlock bb, int i, SourceVariable v |
exists(SsaInput::BasicBlock bb, int i, SsaInput::SourceVariable v |
this.definesAt(v, bb, i) and
definitionAt(result, bb, i, v)
)
}
final AssignableRead getAFirstRead() {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
this.definesAt(_, bb1, i1) and
SsaImpl::adjacentDefRead(this, bb1, i1, bb2, i2) and
result = bb2.getElement(i2)
@@ -42,14 +174,14 @@ module PreSsa {
not result instanceof PhiNode
}
final predicate isLiveAtEndOfBlock(BasicBlock bb) {
final predicate isLiveAtEndOfBlock(SsaInput::BasicBlock bb) {
SsaImpl::ssaDefReachesEndOfBlock(bb, this, _)
}
Location getLocation() {
result = this.getDefinition().getLocation()
or
exists(Callable c, BasicBlock bb, SourceVariable v |
exists(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v |
this.definesAt(v, bb, -1) and
implicitEntryDef(c, bb, v) and
result = c.getLocation()
@@ -64,9 +196,9 @@ module PreSsa {
}
predicate adjacentReadPairSameVar(AssignableRead read1, AssignableRead read2) {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
read1 = bb1.getElement(i1) and
variableRead(bb1, i1, _, true) and
SsaInput::variableRead(bb1, i1, _, true) and
SsaImpl::adjacentDefRead(_, bb1, i1, bb2, i2) and
read2 = bb2.getElement(i2)
)

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,130 +0,0 @@
/** Provides the C# specific parameters for `SsaImplCommon.qll`. */
private import csharp
private import AssignableDefinitions
private import semmle.code.csharp.controlflow.internal.PreBasicBlocks as PreBasicBlocks
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
class BasicBlock = PreBasicBlocks::PreBasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { scopeLast(_, this.getLastElement(), _) }
}
/** Holds if `a` is assigned in non-constructor callable `c`. */
pragma[nomagic]
private predicate assignableDefinition(Assignable a, Callable c) {
exists(AssignableDefinition def | def.getTarget() = a |
c = def.getEnclosingCallable() and
not c instanceof Constructor
)
}
/** Holds if `a` is accessed in callable `c`. */
pragma[nomagic]
private predicate assignableAccess(Assignable a, Callable c) {
exists(AssignableAccess aa | aa.getTarget() = a | c = aa.getEnclosingCallable())
}
pragma[nomagic]
private predicate assignableNoCapturing(Assignable a, Callable c) {
assignableAccess(a, c) and
/*
* The code below is equivalent to
* ```ql
* not exists(Callable other | assignableDefinition(a, other) | other != c)
* ```
* but it avoids a Cartesian product in the compiler generated antijoin
* predicate.
*/
(
not assignableDefinition(a, _)
or
c = unique(Callable c0 | assignableDefinition(a, c0) | c0)
)
}
pragma[noinline]
private predicate assignableNoComplexQualifiers(Assignable a) {
forall(QualifiableExpr qe | qe.(AssignableAccess).getTarget() = a | qe.targetIsThisInstance())
}
/**
* A simple assignable. Either a local scope variable or a field/property
* that behaves like a local scope variable.
*/
class SourceVariable extends Assignable {
private Callable c;
SourceVariable() {
(
this instanceof LocalScopeVariable
or
this = any(Field f | not f.isVolatile())
or
this = any(TrivialProperty tp | not tp.isOverridableOrImplementable())
) and
assignableNoCapturing(this, c) and
assignableNoComplexQualifiers(this)
}
/** Gets a callable in which this simple assignable can be analyzed. */
Callable getACallable() { result = c }
}
predicate definitionAt(AssignableDefinition def, BasicBlock bb, int i, SourceVariable v) {
bb.getElement(i) = def.getExpr() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
or
def.(ImplicitParameterDefinition).getParameter() = v and
exists(Callable c | v = c.getAParameter() |
scopeFirst(c, bb) and
i = -1
)
}
predicate implicitEntryDef(Callable c, BasicBlock bb, SourceVariable v) {
not v instanceof LocalScopeVariable and
c = v.getACallable() and
scopeFirst(c, bb)
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.getTargetAccess().isRefArgument() then certain = false else certain = true
)
or
exists(Callable c |
implicitEntryDef(c, bb, v) and
i = -1 and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read = bb.getElement(i) and
read.getTarget() = v and
certain = true
)
or
v =
any(LocalScopeVariable lsv |
lsv.getCallable() = bb.(ExitBasicBlock).getEnclosingCallable() and
i = bb.length() and
(lsv.isRef() or v.(Parameter).isOut()) and
certain = false
)
}

View File

@@ -12,6 +12,8 @@
* `namespace; type; subtypes; name; signature; ext; input; output; kind; provenance`
* - Negative Summaries:
* `namespace; type; name; signature; provenance`
* A negative summary is used to indicate that there is no flow via a callable.
*
* The interpretation of a row is similar to API-graphs with a left-to-right
* reading.
* 1. The `namespace` column selects a namespace.

View File

@@ -4,19 +4,74 @@ import csharp
* Provides a simple SSA implementation for local scope variables.
*/
module BaseSsa {
import basessa.SsaImplSpecific
private import basessa.SsaImplCommon as SsaImpl
private import AssignableDefinitions
private import semmle.code.csharp.dataflow.internal.SsaImplCommon as SsaImplCommon
/**
* Holds if the `i`th node of basic block `bb` is assignable definition `def`,
* targeting local scope variable `v`.
*/
private predicate definitionAt(
AssignableDefinition def, ControlFlow::BasicBlock bb, int i, SsaInput::SourceVariable v
) {
bb.getNode(i) = def.getAControlFlowNode() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
}
private module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
pragma[noinline]
private Callable getAnAssigningCallable(LocalScopeVariable v) {
result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable()
}
class SourceVariable extends LocalScopeVariable {
SourceVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) }
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.isCertain() then certain = true else certain = false
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read.getAControlFlowNode() = bb.getNode(i) and
read.getTarget() = v and
certain = true
)
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {
exists(BasicBlock bb, int i |
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(_, this, bb, i) and
result.getAControlFlowNode() = bb.getNode(i)
)
}
final AssignableDefinition getDefinition() {
exists(BasicBlock bb, int i, SourceVariable v |
exists(ControlFlow::BasicBlock bb, int i, SsaInput::SourceVariable v |
this.definesAt(v, bb, i) and
definitionAt(result, bb, i, v)
)

View File

@@ -3,7 +3,53 @@
*/
import csharp
import SsaImplCommon
private import SsaImplCommon as SsaImplCommon
private import AssignableDefinitions
private module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
class SourceVariable = Ssa::SourceVariable;
/**
* Holds if the `i`th node of basic block `bb` is a (potential) write to source
* variable `v`. The Boolean `certain` indicates whether the write is certain.
*
* This includes implicit writes via calls.
*/
predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableWriteDirect(bb, i, v, certain)
or
variableWriteQualifier(bb, i, v, certain)
or
updatesNamedFieldOrProp(bb, i, _, v, _) and
certain = false
or
updatesCapturedVariable(bb, i, _, v, _, _) and
certain = false
}
/**
* Holds if the `i`th of basic block `bb` reads source variable `v`.
*
* This includes implicit reads via calls.
*/
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableReadActual(bb, i, v) and
certain = true
or
variableReadPseudo(bb, i, v) and
certain = false
}
}
import SsaImplCommon::Make<SsaInput>
/**
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
@@ -805,24 +851,6 @@ private module CapturedVariableImpl {
}
}
/**
* Holds if the `i`th node of basic block `bb` is a (potential) write to source
* variable `v`. The Boolean `certain` indicates whether the write is certain.
*
* This includes implicit writes via calls.
*/
predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableWriteDirect(bb, i, v, certain)
or
variableWriteQualifier(bb, i, v, certain)
or
updatesNamedFieldOrProp(bb, i, _, v, _) and
certain = false
or
updatesCapturedVariable(bb, i, _, v, _, _) and
certain = false
}
/**
* Liveness analysis to restrict the size of the SSA representation for
* captured variables.
@@ -1039,19 +1067,6 @@ private predicate variableReadPseudo(ControlFlow::BasicBlock bb, int i, Ssa::Sou
capturedReadIn(bb, i, v, _, _, _)
}
/**
* Holds if the `i`th of basic block `bb` reads source variable `v`.
*
* This includes implicit reads via calls.
*/
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableReadActual(bb, i, v) and
certain = true
or
variableReadPseudo(bb, i, v) and
certain = false
}
cached
private module Cached {
cached
@@ -1151,7 +1166,7 @@ private module Cached {
predicate variableWriteQualifier(
ControlFlow::BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v, boolean certain
) {
variableWrite(bb, i, v.getQualifier(), certain) and
SsaInput::variableWrite(bb, i, v.getQualifier(), certain) and
// Eliminate corner case where a call definition can overlap with a
// qualifier definition: if method `M` updates field `F`, then a call
// to `M` is both an update of `x.M` and `x.M.M`, so the former call

View File

@@ -1,19 +0,0 @@
/** Provides the C# specific parameters for `SsaImplCommon.qll`. */
private import csharp
private import AssignableDefinitions
private import SsaImpl as SsaImpl
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
class SourceVariable = Ssa::SourceVariable;
predicate variableWrite = SsaImpl::variableWrite/4;
predicate variableRead = SsaImpl::variableRead/4;

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,51 +0,0 @@
/** Provides the C# specific parameters for `SsaImplCommon.qll`. */
private import csharp
private import AssignableDefinitions
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
pragma[noinline]
private Callable getAnAssigningCallable(LocalScopeVariable v) {
result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable()
}
class SourceVariable extends LocalScopeVariable {
SourceVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) }
}
/**
* Holds if the `i`th node of basic block `bb` is assignable definition `def`,
* targeting local scope variable `v`.
*/
predicate definitionAt(AssignableDefinition def, BasicBlock bb, int i, SourceVariable v) {
bb.getNode(i) = def.getAControlFlowNode() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.isCertain() then certain = true else certain = false
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read.getAControlFlowNode() = bb.getNode(i) and
read.getTarget() = v and
certain = true
)
}

View File

@@ -1,9 +1,8 @@
/** Provides a module for importing negative models. */
/**
* A module importing all generated negative Models as Data models.
*/
import csharp
private module GeneratedFrameworks {
private import generated.dotnet.NegativeRuntime
}

View File

@@ -3237,7 +3237,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.CodeDom.Compiler;IndentedTextWriter;Close;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;DisposeAsync;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;Flush;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;FlushAsync;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;IndentedTextWriter;(System.IO.TextWriter);generated",
"System.CodeDom.Compiler;IndentedTextWriter;OutputTabs;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;OutputTabsAsync;();generated",
@@ -3281,7 +3280,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineAsync;(System.String);generated",
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineAsync;(System.Text.StringBuilder,System.Threading.CancellationToken);generated",
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineNoTabs;(System.String);generated",
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineNoTabsAsync;(System.String);generated",
"System.CodeDom.Compiler;IndentedTextWriter;get_Indent;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;set_Indent;(System.Int32);generated",
"System.CodeDom.Compiler;TempFileCollection;AddFile;(System.String,System.Boolean);generated",
@@ -3459,7 +3457,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.CodeDom;CodeNamespaceImport;set_LinePragma;(System.CodeDom.CodeLinePragma);generated",
"System.CodeDom;CodeNamespaceImportCollection;Clear;();generated",
"System.CodeDom;CodeNamespaceImportCollection;Contains;(System.Object);generated",
"System.CodeDom;CodeNamespaceImportCollection;GetEnumerator;();generated",
"System.CodeDom;CodeNamespaceImportCollection;IndexOf;(System.Object);generated",
"System.CodeDom;CodeNamespaceImportCollection;Remove;(System.Object);generated",
"System.CodeDom;CodeNamespaceImportCollection;RemoveAt;(System.Int32);generated",
@@ -3612,7 +3609,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Concurrent;ConcurrentDictionary<,>;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Contains;(System.Object);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;ContainsKey;(TKey);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;GetEnumerator;();generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Remove;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Remove;(System.Object);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Remove;(TKey);generated",
@@ -3676,9 +3672,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Generic;ByteEqualityComparer;Equals;(System.Object);generated",
"System.Collections.Generic;ByteEqualityComparer;GetHashCode;();generated",
"System.Collections.Generic;ByteEqualityComparer;GetHashCode;(System.Byte);generated",
"System.Collections.Generic;CollectionExtensions;AsReadOnly<,>;(System.Collections.Generic.IDictionary<TKey,TValue>);generated",
"System.Collections.Generic;CollectionExtensions;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>,TKey);generated",
"System.Collections.Generic;CollectionExtensions;TryAdd<,>;(System.Collections.Generic.IDictionary<TKey,TValue>,TKey,TValue);generated",
"System.Collections.Generic;Comparer<>;Compare;(System.Object,System.Object);generated",
"System.Collections.Generic;Comparer<>;Compare;(T,T);generated",
"System.Collections.Generic;Comparer<>;get_Default;();generated",
@@ -3819,7 +3813,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Generic;KeyNotFoundException;KeyNotFoundException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Collections.Generic;KeyNotFoundException;KeyNotFoundException;(System.String);generated",
"System.Collections.Generic;KeyNotFoundException;KeyNotFoundException;(System.String,System.Exception);generated",
"System.Collections.Generic;KeyValuePair;Create<,>;(TKey,TValue);generated",
"System.Collections.Generic;KeyValuePair<,>;ToString;();generated",
"System.Collections.Generic;LinkedList<>+Enumerator;Dispose;();generated",
"System.Collections.Generic;LinkedList<>+Enumerator;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
@@ -4172,9 +4165,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableDictionary;CreateBuilder<,>;();generated",
"System.Collections.Immutable;ImmutableDictionary;CreateBuilder<,>;(System.Collections.Generic.IEqualityComparer<TKey>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateBuilder<,>;(System.Collections.Generic.IEqualityComparer<TKey>,System.Collections.Generic.IEqualityComparer<TValue>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateRange<,>;(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateRange<,>;(System.Collections.Generic.IEqualityComparer<TKey>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateRange<,>;(System.Collections.Generic.IEqualityComparer<TKey>,System.Collections.Generic.IEqualityComparer<TValue>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableDictionary;GetValueOrDefault<,>;(System.Collections.Immutable.IImmutableDictionary<TKey,TValue>,TKey);generated",
"System.Collections.Immutable;ImmutableDictionary<,>+Builder;Clear;();generated",
"System.Collections.Immutable;ImmutableDictionary<,>+Builder;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
@@ -4264,10 +4254,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableInterlocked;TryRemove<,>;(System.Collections.Immutable.ImmutableDictionary<TKey,TValue>,TKey,TValue);generated",
"System.Collections.Immutable;ImmutableInterlocked;TryUpdate<,>;(System.Collections.Immutable.ImmutableDictionary<TKey,TValue>,TKey,TValue,TValue);generated",
"System.Collections.Immutable;ImmutableList;Create<>;();generated",
"System.Collections.Immutable;ImmutableList;Create<>;(T);generated",
"System.Collections.Immutable;ImmutableList;Create<>;(T[]);generated",
"System.Collections.Immutable;ImmutableList;CreateBuilder<>;();generated",
"System.Collections.Immutable;ImmutableList;CreateRange<>;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableList;IndexOf<>;(System.Collections.Immutable.IImmutableList<T>,T);generated",
"System.Collections.Immutable;ImmutableList;IndexOf<>;(System.Collections.Immutable.IImmutableList<T>,T,System.Collections.Generic.IEqualityComparer<T>);generated",
"System.Collections.Immutable;ImmutableList;IndexOf<>;(System.Collections.Immutable.IImmutableList<T>,T,System.Int32);generated",
@@ -4331,9 +4319,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableQueue<>;get_IsEmpty;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary;Create<,>;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateBuilder<,>;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateRange<,>;(System.Collections.Generic.IComparer<TKey>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateRange<,>;(System.Collections.Generic.IComparer<TKey>,System.Collections.Generic.IEqualityComparer<TValue>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateRange<,>;(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Builder;Clear;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Builder;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Builder;Contains;(System.Object);generated",
@@ -4353,7 +4338,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;Dispose;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;MoveNext;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;Reset;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;get_Current;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;Clear;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;Contains;(System.Object);generated",
@@ -4370,8 +4354,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedDictionary<,>;get_IsReadOnly;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;get_IsSynchronized;();generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;();generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;(System.Collections.Generic.IComparer<T>,T);generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;(T[]);generated",
"System.Collections.Immutable;ImmutableSortedSet;CreateBuilder<>;();generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;Clear;();generated",
@@ -4385,7 +4367,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;Overlaps;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;Remove;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;SetEquals;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;get_Count;();generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;get_IsReadOnly;();generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;get_IsSynchronized;();generated",
@@ -4399,7 +4380,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedSet<>;ExceptWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IndexOf;(System.Object);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IndexOf;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;Intersect;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IntersectWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IsProperSubsetOf;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IsProperSupersetOf;(System.Collections.Generic.IEnumerable<T>);generated",
@@ -4411,7 +4391,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedSet<>;Remove;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;RemoveAt;(System.Int32);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;SetEquals;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;UnionWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;get_Count;();generated",
@@ -4819,7 +4798,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;AggregateCatalog;AggregateCatalog;(System.Collections.Generic.IEnumerable<System.ComponentModel.Composition.Primitives.ComposablePartCatalog>);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;AggregateCatalog;(System.ComponentModel.Composition.Primitives.ComposablePartCatalog[]);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;OnChanging;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;AggregateExportProvider;AggregateExportProvider;(System.Collections.Generic.IEnumerable<System.ComponentModel.Composition.Hosting.ExportProvider>);generated",
@@ -4827,13 +4805,11 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;AggregateExportProvider;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;ApplicationCatalog;();generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;ToString;();generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;get_DisplayName;();generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;get_Origin;();generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;AssemblyCatalog;(System.String);generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;get_Origin;();generated",
"System.ComponentModel.Composition.Hosting;AtomicComposition;AtomicComposition;();generated",
"System.ComponentModel.Composition.Hosting;AtomicComposition;Complete;();generated",
@@ -4869,7 +4845,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;CompositionContainer;SatisfyImportsOnce;(System.ComponentModel.Composition.Primitives.ComposablePart);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;CompositionScopeDefinition;();generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;OnChanging;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;CompositionService;Dispose;();generated",
@@ -4879,7 +4854,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;DirectoryCatalog;(System.String,System.Reflection.ReflectionContext);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;DirectoryCatalog;(System.String,System.Reflection.ReflectionContext,System.ComponentModel.Composition.Primitives.ICompositionElement);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;OnChanging;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;Refresh;();generated",
@@ -4902,7 +4876,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;ExportsChangeEventArgs;get_AtomicComposition;();generated",
"System.ComponentModel.Composition.Hosting;ExportsChangeEventArgs;set_AtomicComposition;(System.ComponentModel.Composition.Hosting.AtomicComposition);generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;IncludeDependencies;();generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;IncludeDependents;();generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
@@ -4936,7 +4909,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;ComposablePartCatalog;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;Dispose;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Primitives;ComposablePartDefinition;ComposablePartDefinition;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartDefinition;CreatePart;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartDefinition;get_ExportDefinitions;();generated",
@@ -6364,7 +6336,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel;TypeConverter+SimplePropertyDescriptor;get_ComponentType;();generated",
"System.ComponentModel;TypeConverter+SimplePropertyDescriptor;get_IsReadOnly;();generated",
"System.ComponentModel;TypeConverter+SimplePropertyDescriptor;get_PropertyType;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;GetEnumerator;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;get_Count;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;get_IsSynchronized;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;get_SyncRoot;();generated",
@@ -7511,14 +7482,9 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbCommand;DbCommand;();generated",
"System.Data.Common;DbCommand;DisposeAsync;();generated",
"System.Data.Common;DbCommand;ExecuteDbDataReader;(System.Data.CommandBehavior);generated",
"System.Data.Common;DbCommand;ExecuteDbDataReaderAsync;(System.Data.CommandBehavior,System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteNonQuery;();generated",
"System.Data.Common;DbCommand;ExecuteNonQueryAsync;();generated",
"System.Data.Common;DbCommand;ExecuteNonQueryAsync;(System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;();generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;(System.Data.CommandBehavior);generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;(System.Data.CommandBehavior,System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;(System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteScalar;();generated",
"System.Data.Common;DbCommand;ExecuteScalarAsync;();generated",
"System.Data.Common;DbCommand;ExecuteScalarAsync;(System.Threading.CancellationToken);generated",
@@ -7602,7 +7568,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbConnectionStringBuilder;GetDefaultEvent;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetDefaultProperty;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetEditor;(System.Type);generated",
"System.Data.Common;DbConnectionStringBuilder;GetEnumerator;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetEvents;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetEvents;(System.Attribute[]);generated",
"System.Data.Common;DbConnectionStringBuilder;GetProperties;(System.Collections.Hashtable);generated",
@@ -7670,8 +7635,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbDataReader;GetDecimal;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetDouble;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetFieldType;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetFieldValueAsync<>;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetFieldValueAsync<>;(System.Int32,System.Threading.CancellationToken);generated",
"System.Data.Common;DbDataReader;GetFloat;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetGuid;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetInt16;(System.Int32);generated",
@@ -7681,7 +7644,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbDataReader;GetOrdinal;(System.String);generated",
"System.Data.Common;DbDataReader;GetProviderSpecificFieldType;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetSchemaTable;();generated",
"System.Data.Common;DbDataReader;GetSchemaTableAsync;(System.Threading.CancellationToken);generated",
"System.Data.Common;DbDataReader;GetStream;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetString;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetValue;(System.Int32);generated",
@@ -8993,9 +8955,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataColumnChangeEventArgs;get_ProposedValue;();generated",
"System.Data;DataColumnChangeEventArgs;get_Row;();generated",
"System.Data;DataColumnChangeEventArgs;set_ProposedValue;(System.Object);generated",
"System.Data;DataColumnCollection;Add;();generated",
"System.Data;DataColumnCollection;Add;(System.String,System.Type);generated",
"System.Data;DataColumnCollection;Add;(System.String,System.Type,System.String);generated",
"System.Data;DataColumnCollection;CanRemove;(System.Data.DataColumn);generated",
"System.Data;DataColumnCollection;Clear;();generated",
"System.Data;DataColumnCollection;Contains;(System.String);generated",
@@ -9018,7 +8977,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataReaderExtensions;GetDecimal;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetDouble;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetFieldType;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetFieldValueAsync<>;(System.Data.Common.DbDataReader,System.String,System.Threading.CancellationToken);generated",
"System.Data;DataReaderExtensions;GetFloat;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetInt16;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetInt32;(System.Data.Common.DbDataReader,System.String);generated",
@@ -9036,10 +8994,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataRelation;get_Nested;();generated",
"System.Data;DataRelation;get_ParentTable;();generated",
"System.Data;DataRelation;set_Nested;(System.Boolean);generated",
"System.Data;DataRelationCollection;Add;(System.Data.DataColumn,System.Data.DataColumn);generated",
"System.Data;DataRelationCollection;Add;(System.Data.DataColumn[],System.Data.DataColumn[]);generated",
"System.Data;DataRelationCollection;Add;(System.String,System.Data.DataColumn,System.Data.DataColumn);generated",
"System.Data;DataRelationCollection;Add;(System.String,System.Data.DataColumn[],System.Data.DataColumn[]);generated",
"System.Data;DataRelationCollection;AddCore;(System.Data.DataRelation);generated",
"System.Data;DataRelationCollection;CanRemove;(System.Data.DataRelation);generated",
"System.Data;DataRelationCollection;Clear;();generated",
@@ -9286,7 +9240,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataTableClearEventArgs;get_Table;();generated",
"System.Data;DataTableClearEventArgs;get_TableName;();generated",
"System.Data;DataTableClearEventArgs;get_TableNamespace;();generated",
"System.Data;DataTableCollection;Add;();generated",
"System.Data;DataTableCollection;CanRemove;(System.Data.DataTable);generated",
"System.Data;DataTableCollection;Clear;();generated",
"System.Data;DataTableCollection;Contains;(System.String);generated",
@@ -13442,19 +13395,15 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Drawing.Printing;PrinterResolution;set_X;(System.Int32);generated",
"System.Drawing.Printing;PrinterResolution;set_Y;(System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;CopyTo;(System.Drawing.Printing.PaperSize[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;CopyTo;(System.Drawing.Printing.PaperSource[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;CopyTo;(System.Drawing.Printing.PrinterResolution[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;CopyTo;(System.String[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings;Clone;();generated",
@@ -15785,12 +15734,10 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO.Compression;DeflateStream;EndWrite;(System.IAsyncResult);generated",
"System.IO.Compression;DeflateStream;Flush;();generated",
"System.IO.Compression;DeflateStream;Read;(System.Span<System.Byte>);generated",
"System.IO.Compression;DeflateStream;ReadAsync;(System.Memory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;DeflateStream;ReadByte;();generated",
"System.IO.Compression;DeflateStream;Seek;(System.Int64,System.IO.SeekOrigin);generated",
"System.IO.Compression;DeflateStream;SetLength;(System.Int64);generated",
"System.IO.Compression;DeflateStream;Write;(System.ReadOnlySpan<System.Byte>);generated",
"System.IO.Compression;DeflateStream;WriteAsync;(System.ReadOnlyMemory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;DeflateStream;WriteByte;(System.Byte);generated",
"System.IO.Compression;DeflateStream;get_CanRead;();generated",
"System.IO.Compression;DeflateStream;get_CanSeek;();generated",
@@ -15806,12 +15753,10 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO.Compression;GZipStream;GZipStream;(System.IO.Stream,System.IO.Compression.CompressionLevel);generated",
"System.IO.Compression;GZipStream;GZipStream;(System.IO.Stream,System.IO.Compression.CompressionMode);generated",
"System.IO.Compression;GZipStream;Read;(System.Span<System.Byte>);generated",
"System.IO.Compression;GZipStream;ReadAsync;(System.Memory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;GZipStream;ReadByte;();generated",
"System.IO.Compression;GZipStream;Seek;(System.Int64,System.IO.SeekOrigin);generated",
"System.IO.Compression;GZipStream;SetLength;(System.Int64);generated",
"System.IO.Compression;GZipStream;Write;(System.ReadOnlySpan<System.Byte>);generated",
"System.IO.Compression;GZipStream;WriteAsync;(System.ReadOnlyMemory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;GZipStream;WriteByte;(System.Byte);generated",
"System.IO.Compression;GZipStream;get_CanRead;();generated",
"System.IO.Compression;GZipStream;get_CanSeek;();generated",
@@ -16383,7 +16328,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;BinaryWriter;BinaryWriter;(System.IO.Stream,System.Text.Encoding);generated",
"System.IO;BinaryWriter;Close;();generated", "System.IO;BinaryWriter;Dispose;();generated",
"System.IO;BinaryWriter;Dispose;(System.Boolean);generated",
"System.IO;BinaryWriter;DisposeAsync;();generated",
"System.IO;BinaryWriter;Flush;();generated",
"System.IO;BinaryWriter;Seek;(System.Int32,System.IO.SeekOrigin);generated",
"System.IO;BinaryWriter;Write7BitEncodedInt64;(System.Int64);generated",
@@ -16774,18 +16718,14 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;Stream;DisposeAsync;();generated",
"System.IO;Stream;EndRead;(System.IAsyncResult);generated",
"System.IO;Stream;EndWrite;(System.IAsyncResult);generated",
"System.IO;Stream;Flush;();generated", "System.IO;Stream;FlushAsync;();generated",
"System.IO;Stream;FlushAsync;(System.Threading.CancellationToken);generated",
"System.IO;Stream;ObjectInvariant;();generated",
"System.IO;Stream;Flush;();generated", "System.IO;Stream;ObjectInvariant;();generated",
"System.IO;Stream;Read;(System.Span<System.Byte>);generated",
"System.IO;Stream;ReadAsync;(System.Memory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO;Stream;ReadByte;();generated",
"System.IO;Stream;Seek;(System.Int64,System.IO.SeekOrigin);generated",
"System.IO;Stream;SetLength;(System.Int64);generated",
"System.IO;Stream;ValidateBufferArguments;(System.Byte[],System.Int32,System.Int32);generated",
"System.IO;Stream;ValidateCopyToArguments;(System.IO.Stream,System.Int32);generated",
"System.IO;Stream;Write;(System.ReadOnlySpan<System.Byte>);generated",
"System.IO;Stream;WriteAsync;(System.ReadOnlyMemory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO;Stream;WriteByte;(System.Byte);generated",
"System.IO;Stream;get_CanRead;();generated", "System.IO;Stream;get_CanSeek;();generated",
"System.IO;Stream;get_CanTimeout;();generated",
@@ -16805,7 +16745,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;StreamWriter;Dispose;(System.Boolean);generated",
"System.IO;StreamWriter;DisposeAsync;();generated",
"System.IO;StreamWriter;Flush;();generated",
"System.IO;StreamWriter;FlushAsync;();generated",
"System.IO;StreamWriter;StreamWriter;(System.IO.Stream);generated",
"System.IO;StreamWriter;StreamWriter;(System.IO.Stream,System.Text.Encoding);generated",
"System.IO;StreamWriter;StreamWriter;(System.IO.Stream,System.Text.Encoding,System.Int32);generated",
@@ -16824,15 +16763,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;StreamWriter;Write;(System.String,System.Object,System.Object);generated",
"System.IO;StreamWriter;Write;(System.String,System.Object,System.Object,System.Object);generated",
"System.IO;StreamWriter;Write;(System.String,System.Object[]);generated",
"System.IO;StreamWriter;WriteAsync;(System.Char);generated",
"System.IO;StreamWriter;WriteAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;StreamWriter;WriteAsync;(System.String);generated",
"System.IO;StreamWriter;WriteLine;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;StreamWriter;WriteLine;(System.String);generated",
"System.IO;StreamWriter;WriteLineAsync;();generated",
"System.IO;StreamWriter;WriteLineAsync;(System.Char);generated",
"System.IO;StreamWriter;WriteLineAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;StreamWriter;WriteLineAsync;(System.String);generated",
"System.IO;StreamWriter;get_AutoFlush;();generated",
"System.IO;StreamWriter;set_AutoFlush;(System.Boolean);generated",
"System.IO;StringReader;Close;();generated",
@@ -16845,10 +16777,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;StringWriter;StringWriter;(System.Text.StringBuilder);generated",
"System.IO;StringWriter;Write;(System.Char);generated",
"System.IO;StringWriter;Write;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;StringWriter;Write;(System.Text.StringBuilder);generated",
"System.IO;StringWriter;WriteAsync;(System.Char);generated",
"System.IO;StringWriter;WriteLine;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;StringWriter;WriteLine;(System.Text.StringBuilder);generated",
"System.IO;StringWriter;WriteLineAsync;(System.Char);generated",
"System.IO;StringWriter;get_Encoding;();generated",
"System.IO;TextReader;Close;();generated", "System.IO;TextReader;Dispose;();generated",
@@ -16857,7 +16787,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;TextWriter;Close;();generated", "System.IO;TextWriter;Dispose;();generated",
"System.IO;TextWriter;Dispose;(System.Boolean);generated",
"System.IO;TextWriter;DisposeAsync;();generated", "System.IO;TextWriter;Flush;();generated",
"System.IO;TextWriter;FlushAsync;();generated",
"System.IO;TextWriter;TextWriter;();generated",
"System.IO;TextWriter;Write;(System.Boolean);generated",
"System.IO;TextWriter;Write;(System.Char);generated",
@@ -16872,9 +16801,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;TextWriter;Write;(System.Text.StringBuilder);generated",
"System.IO;TextWriter;Write;(System.UInt32);generated",
"System.IO;TextWriter;Write;(System.UInt64);generated",
"System.IO;TextWriter;WriteAsync;(System.Char);generated",
"System.IO;TextWriter;WriteAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;TextWriter;WriteAsync;(System.String);generated",
"System.IO;TextWriter;WriteLine;();generated",
"System.IO;TextWriter;WriteLine;(System.Boolean);generated",
"System.IO;TextWriter;WriteLine;(System.Char);generated",
@@ -16884,13 +16810,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;TextWriter;WriteLine;(System.Int64);generated",
"System.IO;TextWriter;WriteLine;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;TextWriter;WriteLine;(System.Single);generated",
"System.IO;TextWriter;WriteLine;(System.Text.StringBuilder);generated",
"System.IO;TextWriter;WriteLine;(System.UInt32);generated",
"System.IO;TextWriter;WriteLine;(System.UInt64);generated",
"System.IO;TextWriter;WriteLineAsync;();generated",
"System.IO;TextWriter;WriteLineAsync;(System.Char);generated",
"System.IO;TextWriter;WriteLineAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;TextWriter;WriteLineAsync;(System.String);generated",
"System.IO;TextWriter;get_Encoding;();generated",
"System.IO;UnmanagedMemoryAccessor;Dispose;();generated",
"System.IO;UnmanagedMemoryAccessor;Dispose;(System.Boolean);generated",
@@ -18094,7 +18015,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http.Headers;HttpHeadersNonValidated+Enumerator;Reset;();generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;Contains;(System.String);generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;ContainsKey;(System.String);generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;GetEnumerator;();generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;get_Count;();generated",
"System.Net.Http.Headers;HttpRequestHeaders;get_Accept;();generated",
"System.Net.Http.Headers;HttpRequestHeaders;get_AcceptCharset;();generated",
@@ -18283,7 +18203,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http.Json;JsonContent;TryComputeLength;(System.Int64);generated",
"System.Net.Http.Json;JsonContent;get_ObjectType;();generated",
"System.Net.Http.Json;JsonContent;get_Value;();generated",
"System.Net.Http;ByteArrayContent;CreateContentReadStreamAsync;();generated",
"System.Net.Http;ByteArrayContent;TryComputeLength;(System.Int64);generated",
"System.Net.Http;DelegatingHandler;DelegatingHandler;();generated",
"System.Net.Http;DelegatingHandler;Dispose;(System.Boolean);generated",
@@ -18383,7 +18302,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http;HttpClientHandler;set_UseDefaultCredentials;(System.Boolean);generated",
"System.Net.Http;HttpClientHandler;set_UseProxy;(System.Boolean);generated",
"System.Net.Http;HttpContent;CreateContentReadStreamAsync;();generated",
"System.Net.Http;HttpContent;CreateContentReadStreamAsync;(System.Threading.CancellationToken);generated",
"System.Net.Http;HttpContent;Dispose;();generated",
"System.Net.Http;HttpContent;Dispose;(System.Boolean);generated",
"System.Net.Http;HttpContent;HttpContent;();generated",
@@ -18472,7 +18390,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http;MultipartContent;get_HeaderEncodingSelector;();generated",
"System.Net.Http;MultipartFormDataContent;MultipartFormDataContent;();generated",
"System.Net.Http;MultipartFormDataContent;MultipartFormDataContent;(System.String);generated",
"System.Net.Http;ReadOnlyMemoryContent;CreateContentReadStreamAsync;();generated",
"System.Net.Http;ReadOnlyMemoryContent;SerializeToStream;(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken);generated",
"System.Net.Http;ReadOnlyMemoryContent;SerializeToStreamAsync;(System.IO.Stream,System.Net.TransportContext);generated",
"System.Net.Http;ReadOnlyMemoryContent;SerializeToStreamAsync;(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken);generated",
@@ -19103,7 +19020,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Quic;QuicStreamAbortedException;QuicStreamAbortedException;(System.String,System.Int64);generated",
"System.Net.Quic;QuicStreamAbortedException;get_ErrorCode;();generated",
"System.Net.Security;AuthenticatedStream;Dispose;(System.Boolean);generated",
"System.Net.Security;AuthenticatedStream;DisposeAsync;();generated",
"System.Net.Security;AuthenticatedStream;get_IsAuthenticated;();generated",
"System.Net.Security;AuthenticatedStream;get_IsEncrypted;();generated",
"System.Net.Security;AuthenticatedStream;get_IsMutuallyAuthenticated;();generated",
@@ -19328,7 +19244,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;SendPacketsElement;set_MemoryBuffer;(System.Nullable<System.ReadOnlyMemory<System.Byte>>);generated",
"System.Net.Sockets;SendPacketsElement;set_OffsetLong;(System.Int64);generated",
"System.Net.Sockets;Socket;AcceptAsync;();generated",
"System.Net.Sockets;Socket;AcceptAsync;(System.Net.Sockets.Socket);generated",
"System.Net.Sockets;Socket;CancelConnectAsync;(System.Net.Sockets.SocketAsyncEventArgs);generated",
"System.Net.Sockets;Socket;Close;();generated",
"System.Net.Sockets;Socket;Close;(System.Int32);generated",
@@ -19343,7 +19258,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;Socket;DuplicateAndClose;(System.Int32);generated",
"System.Net.Sockets;Socket;EndAccept;(System.Byte[],System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndAccept;(System.Byte[],System.Int32,System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndAccept;(System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndConnect;(System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndDisconnect;(System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndReceive;(System.IAsyncResult);generated",
@@ -19378,10 +19292,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;Socket;ReceiveAsync;(System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;Socket;ReceiveAsync;(System.Collections.Generic.IList<System.ArraySegment<System.Byte>>);generated",
"System.Net.Sockets;Socket;ReceiveAsync;(System.Collections.Generic.IList<System.ArraySegment<System.Byte>>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;Socket;ReceiveFromAsync;(System.ArraySegment<System.Byte>,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;ReceiveFromAsync;(System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;ReceiveMessageFromAsync;(System.ArraySegment<System.Byte>,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;ReceiveMessageFromAsync;(System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;Select;(System.Collections.IList,System.Collections.IList,System.Collections.IList,System.Int32);generated",
"System.Net.Sockets;Socket;Send;(System.Byte[]);generated",
"System.Net.Sockets;Socket;Send;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags);generated",
@@ -19481,14 +19391,11 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;SocketInformation;set_Options;(System.Net.Sockets.SocketInformationOptions);generated",
"System.Net.Sockets;SocketInformation;set_ProtocolInformation;(System.Byte[]);generated",
"System.Net.Sockets;SocketTaskExtensions;AcceptAsync;(System.Net.Sockets.Socket);generated",
"System.Net.Sockets;SocketTaskExtensions;AcceptAsync;(System.Net.Sockets.Socket,System.Net.Sockets.Socket);generated",
"System.Net.Sockets;SocketTaskExtensions;ConnectAsync;(System.Net.Sockets.Socket,System.Net.IPAddress[],System.Int32);generated",
"System.Net.Sockets;SocketTaskExtensions;ConnectAsync;(System.Net.Sockets.Socket,System.Net.IPAddress[],System.Int32,System.Threading.CancellationToken);generated",
"System.Net.Sockets;SocketTaskExtensions;ConnectAsync;(System.Net.Sockets.Socket,System.String,System.Int32);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveAsync;(System.Net.Sockets.Socket,System.Collections.Generic.IList<System.ArraySegment<System.Byte>>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveFromAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveMessageFromAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;SocketTaskExtensions;SendAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;SocketTaskExtensions;SendAsync;(System.Net.Sockets.Socket,System.Collections.Generic.IList<System.ArraySegment<System.Byte>>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;TcpClient;Close;();generated",
@@ -19530,8 +19437,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;TcpListener;AcceptTcpClientAsync;(System.Threading.CancellationToken);generated",
"System.Net.Sockets;TcpListener;AllowNatTraversal;(System.Boolean);generated",
"System.Net.Sockets;TcpListener;Create;(System.Int32);generated",
"System.Net.Sockets;TcpListener;EndAcceptSocket;(System.IAsyncResult);generated",
"System.Net.Sockets;TcpListener;EndAcceptTcpClient;(System.IAsyncResult);generated",
"System.Net.Sockets;TcpListener;Pending;();generated",
"System.Net.Sockets;TcpListener;Start;();generated",
"System.Net.Sockets;TcpListener;Start;(System.Int32);generated",
@@ -19748,10 +19653,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;CredentialCache;Remove;(System.Uri,System.String);generated",
"System.Net;CredentialCache;get_DefaultCredentials;();generated",
"System.Net;CredentialCache;get_DefaultNetworkCredentials;();generated",
"System.Net;Dns;EndGetHostAddresses;(System.IAsyncResult);generated",
"System.Net;Dns;EndGetHostByName;(System.IAsyncResult);generated",
"System.Net;Dns;EndGetHostEntry;(System.IAsyncResult);generated",
"System.Net;Dns;EndResolve;(System.IAsyncResult);generated",
"System.Net;Dns;GetHostAddresses;(System.String);generated",
"System.Net;Dns;GetHostAddresses;(System.String,System.Net.Sockets.AddressFamily);generated",
"System.Net;Dns;GetHostAddressesAsync;(System.String);generated",
@@ -19795,8 +19696,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;EndpointPermission;get_Port;();generated",
"System.Net;EndpointPermission;get_Transport;();generated",
"System.Net;FileWebRequest;Abort;();generated",
"System.Net;FileWebRequest;EndGetRequestStream;(System.IAsyncResult);generated",
"System.Net;FileWebRequest;EndGetResponse;(System.IAsyncResult);generated",
"System.Net;FileWebRequest;FileWebRequest;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;FileWebRequest;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;FileWebRequest;GetRequestStreamAsync;();generated",
@@ -19951,9 +19850,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;HttpWebRequest;AddRange;(System.String,System.Int32,System.Int32);generated",
"System.Net;HttpWebRequest;AddRange;(System.String,System.Int64);generated",
"System.Net;HttpWebRequest;AddRange;(System.String,System.Int64,System.Int64);generated",
"System.Net;HttpWebRequest;EndGetRequestStream;(System.IAsyncResult);generated",
"System.Net;HttpWebRequest;EndGetRequestStream;(System.IAsyncResult,System.Net.TransportContext);generated",
"System.Net;HttpWebRequest;EndGetResponse;(System.IAsyncResult);generated",
"System.Net;HttpWebRequest;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;HttpWebRequest;HttpWebRequest;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;HttpWebRequest;get_AllowAutoRedirect;();generated",
@@ -20102,7 +19998,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;NetworkCredential;get_SecurePassword;();generated",
"System.Net;NetworkCredential;set_SecurePassword;(System.Security.SecureString);generated",
"System.Net;PathList;GetCookiesCount;();generated",
"System.Net;PathList;get_Count;();generated", "System.Net;PathList;get_Values;();generated",
"System.Net;PathList;get_Count;();generated",
"System.Net;PathList;set_Item;(System.String,System.Object);generated",
"System.Net;ProtocolViolationException;ProtocolViolationException;();generated",
"System.Net;ProtocolViolationException;ProtocolViolationException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
@@ -20488,6 +20384,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Numerics;BigInteger;Log;(System.Numerics.BigInteger,System.Double);generated",
"System.Numerics;BigInteger;ModPow;(System.Numerics.BigInteger,System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;Multiply;(System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;Negate;(System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;Parse;(System.ReadOnlySpan<System.Char>,System.Globalization.NumberStyles,System.IFormatProvider);generated",
"System.Numerics;BigInteger;Parse;(System.String);generated",
"System.Numerics;BigInteger;Parse;(System.String,System.Globalization.NumberStyles);generated",
@@ -20553,6 +20450,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Numerics;BigInteger;op_Multiply;(System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;op_OnesComplement;(System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;op_Subtraction;(System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;op_UnaryNegation;(System.Numerics.BigInteger);generated",
"System.Numerics;BitOperations;IsPow2;(System.Int32);generated",
"System.Numerics;BitOperations;IsPow2;(System.Int64);generated",
"System.Numerics;BitOperations;IsPow2;(System.IntPtr);generated",
@@ -23476,7 +23374,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Resources;ResourceSet;Dispose;(System.Boolean);generated",
"System.Resources;ResourceSet;GetDefaultReader;();generated",
"System.Resources;ResourceSet;GetDefaultWriter;();generated",
"System.Resources;ResourceSet;GetEnumerator;();generated",
"System.Resources;ResourceSet;GetObject;(System.String);generated",
"System.Resources;ResourceSet;GetObject;(System.String,System.Boolean);generated",
"System.Resources;ResourceSet;GetString;(System.String);generated",
@@ -23691,6 +23588,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Runtime.CompilerServices;DisablePrivateReflectionAttribute;DisablePrivateReflectionAttribute;();generated",
"System.Runtime.CompilerServices;DiscardableAttribute;DiscardableAttribute;();generated",
"System.Runtime.CompilerServices;DynamicAttribute;DynamicAttribute;();generated",
"System.Runtime.CompilerServices;DynamicAttribute;DynamicAttribute;(System.Boolean[]);generated",
"System.Runtime.CompilerServices;DynamicAttribute;get_TransformFlags;();generated",
"System.Runtime.CompilerServices;EnumeratorCancellationAttribute;EnumeratorCancellationAttribute;();generated",
"System.Runtime.CompilerServices;FixedAddressValueTypeAttribute;FixedAddressValueTypeAttribute;();generated",
"System.Runtime.CompilerServices;FixedBufferAttribute;FixedBufferAttribute;(System.Type,System.Int32);generated",
@@ -29676,7 +29575,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Decrypt;(System.ReadOnlySpan<System.Byte>);generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Decrypt;(System.ReadOnlySpan<System.Char>);generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Decrypt;(System.String);generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;GetBags;();generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Pkcs12SafeContents;();generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;get_ConfidentialityMode;();generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;get_IsReadOnly;();generated",
@@ -29984,7 +29882,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.X509Certificates;X509Certificate;get_Handle;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection+X509CertificateEnumerator;MoveNext;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection+X509CertificateEnumerator;Reset;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection+X509CertificateEnumerator;X509CertificateEnumerator;(System.Security.Cryptography.X509Certificates.X509CertificateCollection);generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection;Contains;(System.Security.Cryptography.X509Certificates.X509Certificate);generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection;GetHashCode;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection;IndexOf;(System.Security.Cryptography.X509Certificates.X509Certificate);generated",
@@ -30154,7 +30051,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.Xml;EncryptionPropertyCollection;get_IsReadOnly;();generated",
"System.Security.Cryptography.Xml;EncryptionPropertyCollection;get_IsSynchronized;();generated",
"System.Security.Cryptography.Xml;IRelDecryptor;Decrypt;(System.Security.Cryptography.Xml.EncryptionMethod,System.Security.Cryptography.Xml.KeyInfo,System.IO.Stream);generated",
"System.Security.Cryptography.Xml;KeyInfo;GetEnumerator;(System.Type);generated",
"System.Security.Cryptography.Xml;KeyInfo;GetXml;();generated",
"System.Security.Cryptography.Xml;KeyInfo;KeyInfo;();generated",
"System.Security.Cryptography.Xml;KeyInfo;get_Count;();generated",
@@ -30221,7 +30117,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.Xml;Transform;Transform;();generated",
"System.Security.Cryptography.Xml;Transform;get_InputTypes;();generated",
"System.Security.Cryptography.Xml;Transform;get_OutputTypes;();generated",
"System.Security.Cryptography.Xml;TransformChain;GetEnumerator;();generated",
"System.Security.Cryptography.Xml;TransformChain;TransformChain;();generated",
"System.Security.Cryptography.Xml;TransformChain;get_Count;();generated",
"System.Security.Cryptography.Xml;X509IssuerSerial;get_IssuerName;();generated",
@@ -34394,7 +34289,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Text.Json.Serialization;ReferenceResolver;GetReference;(System.Object,System.Boolean);generated",
"System.Text.Json.Serialization;ReferenceResolver;ResolveReference;(System.String);generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;Execute;(Microsoft.CodeAnalysis.GeneratorExecutionContext);generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;GetSerializableTypes;();generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;Initialize;(Microsoft.CodeAnalysis.GeneratorInitializationContext);generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;Initialize;(Microsoft.CodeAnalysis.IncrementalGeneratorInitializationContext);generated",
"System.Text.Json;JsonDocument;Dispose;();generated",
@@ -35424,7 +35318,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Threading.RateLimiting;MetadataName<>;op_Inequality;(System.Threading.RateLimiting.MetadataName<>,System.Threading.RateLimiting.MetadataName<>);generated",
"System.Threading.RateLimiting;RateLimitLease;Dispose;();generated",
"System.Threading.RateLimiting;RateLimitLease;Dispose;(System.Boolean);generated",
"System.Threading.RateLimiting;RateLimitLease;GetAllMetadata;();generated",
"System.Threading.RateLimiting;RateLimitLease;TryGetMetadata;(System.String,System.Object);generated",
"System.Threading.RateLimiting;RateLimitLease;get_IsAcquired;();generated",
"System.Threading.RateLimiting;RateLimitLease;get_MetadataNames;();generated",
@@ -35507,10 +35400,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Threading.Tasks.Dataflow;DataflowBlock;OutputAvailableAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;OutputAvailableAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAllAsync<>;(System.Threading.Tasks.Dataflow.IReceivableSourceBlock<TOutput>,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.TimeSpan);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.TimeSpan,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;SendAsync<>;(System.Threading.Tasks.Dataflow.ITargetBlock<TInput>,TInput);generated",
"System.Threading.Tasks.Dataflow;DataflowBlockOptions;DataflowBlockOptions;();generated",
"System.Threading.Tasks.Dataflow;DataflowBlockOptions;get_BoundedCapacity;();generated",
@@ -36723,13 +36612,10 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Xml.Schema;XmlSchemaParticle;set_MinOccursString;(System.String);generated",
"System.Xml.Schema;XmlSchemaPatternFacet;XmlSchemaPatternFacet;();generated",
"System.Xml.Schema;XmlSchemaRedefine;XmlSchemaRedefine;();generated",
"System.Xml.Schema;XmlSchemaSet;Add;(System.Xml.Schema.XmlSchemaSet);generated",
"System.Xml.Schema;XmlSchemaSet;Compile;();generated",
"System.Xml.Schema;XmlSchemaSet;Contains;(System.String);generated",
"System.Xml.Schema;XmlSchemaSet;Contains;(System.Xml.Schema.XmlSchema);generated",
"System.Xml.Schema;XmlSchemaSet;CopyTo;(System.Xml.Schema.XmlSchema[],System.Int32);generated",
"System.Xml.Schema;XmlSchemaSet;RemoveRecursive;(System.Xml.Schema.XmlSchema);generated",
"System.Xml.Schema;XmlSchemaSet;Schemas;();generated",
"System.Xml.Schema;XmlSchemaSet;Schemas;(System.String);generated",
"System.Xml.Schema;XmlSchemaSet;XmlSchemaSet;();generated",
"System.Xml.Schema;XmlSchemaSet;get_Count;();generated",
@@ -36982,7 +36868,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Xml.Serialization;XmlSerializationWriter;WriteEmptyTag;(System.String,System.String);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteEndElement;();generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteEndElement;(System.Object);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteId;(System.Object);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNamespaceDeclarations;(System.Xml.Serialization.XmlSerializerNamespaces);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNullTagEncoded;(System.String);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNullTagEncoded;(System.String,System.String);generated",
@@ -36991,8 +36876,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Xml.Serialization;XmlSerializationWriter;WriteNullableQualifiedNameEncoded;(System.String,System.String,System.Xml.XmlQualifiedName,System.Xml.XmlQualifiedName);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNullableQualifiedNameLiteral;(System.String,System.String,System.Xml.XmlQualifiedName);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteReferencedElements;();generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteReferencingElement;(System.String,System.String,System.Object);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteReferencingElement;(System.String,System.String,System.Object,System.Boolean);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteStartDocument;();generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteStartElement;(System.String);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteStartElement;(System.String,System.String);generated",
@@ -41163,29 +41046,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System;Tuple<>;Equals;(System.Object,System.Collections.IEqualityComparer);generated",
"System;Tuple<>;GetHashCode;();generated",
"System;Tuple<>;GetHashCode;(System.Collections.IEqualityComparer);generated",
"System;Tuple<>;get_Length;();generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18,T19,T20,T21>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18,T19,T20>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18,T19>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7>);generated",
"System;TupleExtensions;ToTuple<,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6>);generated",
"System;TupleExtensions;ToTuple<,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5>);generated",
"System;TupleExtensions;ToTuple<,,,>;(System.ValueTuple<T1,T2,T3,T4>);generated",
"System;TupleExtensions;ToTuple<,,>;(System.ValueTuple<T1,T2,T3>);generated",
"System;TupleExtensions;ToTuple<,>;(System.ValueTuple<T1,T2>);generated",
"System;TupleExtensions;ToTuple<>;(System.ValueTuple<T1>);generated",
"System;Type;Equals;(System.Object);generated",
"System;Tuple<>;get_Length;();generated", "System;Type;Equals;(System.Object);generated",
"System;Type;Equals;(System.Type);generated", "System;Type;GetArrayRank;();generated",
"System;Type;GetAttributeFlagsImpl;();generated",
"System;Type;GetConstructorImpl;(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[]);generated",

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