Merge rc/1.18 into next.

This commit is contained in:
Aditya Sharad
2018-09-12 14:59:54 +01:00
120 changed files with 4726 additions and 3692 deletions

View File

@@ -1,40 +1,28 @@
# Improvements to C/C++ analysis
## General improvements
> Changes that affect alerts in many files or from many queries
> For example, changes to file classification
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Upcast array used in pointer arithmetic | reliability, correctness, external/cwe/cwe-119 | Finds undefined behavior caused by doing pointer arithmetic on an array of objects that has been cast to an array of a supertype. |
| Upcast array used in pointer arithmetic (`cpp/upcast-array-pointer-arithmetic`) | reliability, correctness, external/cwe/cwe-119 | Finds undefined behavior caused by doing pointer arithmetic on an array of objects that has been cast to an array of a supertype. |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| Self comparison | Fewer false positive results | Range checks of the form `x == (T)x` are no longer flagged unless they are guaranteed to have the same result on all platforms. |
| [Nested loops with same variable] | Fewer false positive results | Results where the loop variable is a member of a class or struct now account for the object. |
| [For loop variable changed in body] | Fewer false positive results | Results where the loop variable is a member of a class or struct now account for the object. |
| [Local variable hides global variable] | Fewer false positive results | Results for parameters are now only reported if the name of the global variable is the same as the name of the parameter as used in the function definition (not just a function declaration). |
| [Memory may not be freed] | More correct results | This query now models calls to `realloc` more accurately. |
| Wrong number of arguments to formatting function | Fewer false positive results | Some false positives related to custom printf-like functions have been fixed. |
| Wrong number of arguments to formatting function | Clear separation between results of high and low severity | This query has been split into two queries: a high-severity query named [Too few arguments to formatting function] and a low-severity query named [Too many arguments to formatting function]. |
| [Too few arguments to formatting function] | More correct and fewer false positives results | This query now understands positional format arguments as supported by some libraries. |
| [Too many arguments to formatting function] | More correct and fewer false positives results | This query now understands positional format arguments as supported by some libraries. |
| [Variable used in its own initializer] | Fewer false positive results | Results where a macro is used to indicate deliberate uninitialization are now excluded |
| [Assignment where comparison was intended] | Fewer false positive results | Results are no longer reported if the variable is not yet defined. |
| [Comparison where assignment was intended] | More correct results | "This query now includes results where an overloaded `operator==` is used in the wrong context. |
| [User-controlled data in arithmetic expression] | More correct results | Increment / decrement / addition assignment / subtraction assignment operations are now understood as arithmetic operations in this query. |
| [Uncontrolled data in arithmetic expression] | More correct results | Increment / decrement / addition assignment / subtraction assignment operations are now understood as arithmetic operations in this query. |
| [Use of extreme values in arithmetic expression] | More correct results | Increment / decrement / addition assignment / subtraction assignment operations are now understood as arithmetic operations in this query. |
| [Use of extreme values in arithmetic expression] | Fewer false positives | The query now considers whether a particular expression might cause an overflow of minimum or maximum values only. |
| Assignment where comparison was intended (`cpp/assign-where-compare-meant`) | Fewer false positive results | Results are no longer reported if the variable is not yet defined. |
| Comparison where assignment was intended (`cpp/compare-where-assign-meant`) | More results | This query now includes results where an overloaded `operator==` is used in the wrong context. |
| For loop variable changed in body (`cpp/loop-variable-changed`) | Fewer false positive results | Results where the loop variable is a member of a class or struct now account for the object. |
| Local variable hides global variable (`cpp/local-variable-hides-global-variable`) | Fewer false positive results | Results for parameters are now only reported if the name of the global variable is the same as the name of the parameter as used in the function definition (not just a function declaration). |
| Nested loops with same variable (`cpp/nested-loops-with-same-variable`) | Fewer false positive results | Results where the loop variable is a member of a class or struct now account for the object. |
| Self comparison (`cpp/comparison-of-identical-expressions`) | Fewer false positive results | Range checks of the form `x == (T)x` are no longer flagged unless they are guaranteed to have the same result on all platforms. |
| Too few arguments to formatting function (`cpp/wrong-number-format-arguments`) | More precise results | This was previously known as "Wrong number of arguments to formatting function". It now focuses only on functions calls that are missing arguments, which tend to be more severe. See the next row for the new query that reports lower-severity alerts for calls with too many arguments. In addition, both queries now understand positional format arguments as supported by some libraries, and some false positive results for custom printf-like functions have been fixed.|
| Too many arguments to formatting function (`cpp/too-many-format-arguments`) | More precise results | This new query was created by splitting the old "Wrong number of arguments to formatting function" query (see row above). It reports function calls with too many arguments. |
| User-controlled data in arithmetic expression (`cpp/tainted-arithmetic`) | More results | The query is extended to analyze increment, decrement, addition-assignment, and subtraction-assignment operations. |
| Variable used in its own initializer (`cpp/use-in-own-initializer`) | Fewer false positive results | Results where a macro is used to indicate deliberate uninitialization are now excluded. |
|Uncontrolled data in arithmetic expression (`cpp/uncontrolled-arithmetic`) | More results | The query is extended to analyze increment, decrement, addition-assignment, and subtraction-assignment operations. |
## Changes to QL libraries
* Fixes for aggregate initializers using designators:
* `ClassAggregateLiteral.getFieldExpr()` previously assumed initializer expressions appeared in the same order as the declaration order of the fields, causing it to associate the expressions with the wrong fields when using designated initializers. This has been fixed.
* `ArrayAggregateLiteral.getElementExpr()` previously assumed initializer expressions appeared in the same order as the corresponding array elements, causing it to associate the expressions with the wrong array elements when using designated initializers. This has been fixed.
* `Element.getEnclosingElement()` no longer includes macro accesses in its results. To explore parents and children of macro accesses, use the relevant member predicates on `MacroAccess` or `MacroInvocation`.
* The `ClassAggregateLiteral.getFieldExpr()` and `ArrayAggregateLiteral.getElementExpr()` predicates incorrectly assumed that initializer expressions appeared in the same order as the declaration order of the elements. This resulted in the association of the expressions with the wrong elements when designated initializers were used. This has been fixed.
* Results for the `Element.getEnclosingElement()` predicate no longer included macro accesses. To explore parents and children of macro accesses, use the relevant member predicates on `MacroAccess` or `MacroInvocation`.

View File

@@ -1,11 +1,5 @@
# Improvements to C# analysis
> NOTES
>
> Please describe your changes in terms that are suitable for
> customers to read. These notes will have only minor tidying up
> before they are published as part of the release notes.
## General improvements
* Control flow analysis has been improved for `catch` clauses with filters.
@@ -14,30 +8,53 @@
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Arbitrary file write during zip extraction ("Zip Slip") (`cs/zipslip`) | security, external/cwe/cwe-022 | Identifies zip extraction routines which allow arbitrary file overwrite vulnerabilities.
| Arbitrary file write during zip extraction ("Zip Slip") (`cs/zipslip`) | security, external/cwe/cwe-022 | Identifies zip extraction routines which allow arbitrary file overwrite vulnerabilities. |
| Local scope variable shadows member (`cs/local-shadows-member`) | maintainability, readability | Replaces the existing queries Local variable shadows class member (`cs/local-shadows-class-member`), Local variable shadows struct member (`cs/local-shadows-struct-member`), Parameter shadows class member (`cs/parameter-shadows-class-member`), and Parameter shadows struct member (`cs/parameter-shadows-struct-member`). |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| [Constant condition](https://help.semmle.com/wiki/display/CSHARP/Constant+condition) (`cs/constant-condition`) | More results | The query has been generalized to cover both Null-coalescing left operand is constant (`cs/constant-null-coalescing`) and Switch selector is constant (`cs/constant-switch-selector`). |
| Constant condition (`cs/constant-condition`) | More results | The query has been generalized to report alerts for the old queries Null-coalescing left operand is constant (`cs/constant-null-coalescing`) and Switch selector is constant (`cs/constant-switch-selector`). |
| Exposing internal representation (`cs/expose-implementation`) | Different results | The query has been rewritten, based on the [equivalent Java query](https://help.semmle.com/wiki/display/JAVA/Exposing+internal+representation). |
| Local variable shadows class member(`cs/local-shadows-class-member`) | No results | The query has been replaced by Local scope variable shadows member (`cs/local-shadows-member`). |
| Local variable shadows struct member (`cs/local-shadows-struct-member`) | No results | The query has been replaced by Local scope variable shadows member (`cs/local-shadows-member`). |
| [Missing Dispose call on local IDisposable](https://help.semmle.com/wiki/display/CSHARP/Missing+Dispose+call+on+local+IDisposable) (`cs/local-not-disposed`) | Fewer results | The query identifies more cases where the local variable may be disposed by a library call. |
| [Nested loops with same variable](https://help.semmle.com/wiki/display/CSHARP/Nested+loops+with+same+variable) (`cs/nested-loops-with-same-variable`) | Fewer results | Results are no longer highlighted in nested loops that share the same condition, and do not use the variable after the inner loop. |
| Null-coalescing left operand is constant (`cs/constant-null-coalescing`) | No results | The query has been removed, as it is now covered by Constant condition (`cs/constant-condition`). |
| Parameter shadows class member (`cs/parameter-shadows-class-member`) | No results | The query has been replaced by Local scope variable shadows member (`cs/local-shadows-member`). |
| Parameter shadows struct member (`cs/parameter-shadows-struct-member`) | No results | The query has been replaced by Local scope variable shadows member (`cs/local-shadows-member`). |
| [Potentially incorrect CompareTo(...) signature](https://help.semmle.com/wiki/display/CSHARP/Potentially+incorrect+CompareTo%28...%29+signature) (`cs/wrong-compareto-signature`) | Fewer results | Results are no longer highlighted in constructed types. |
| Switch selector is constant (`cs/constant-switch-selector`) | No results | The query has been removed, as it is now covered by Constant condition (`cs/constant-condition`). |
| [Useless upcast](https://help.semmle.com/wiki/display/CSHARP/Useless+upcast) (`cs/useless-upcast`) | Fewer results | The query has been improved to cover more cases where upcasts may be needed. |
| Local variable shadows class member (`cs/local-shadows-class-member`) | No results | The query has been replaced by the new query: Local scope variable shadows member (`cs/local-shadows-member`). |
| Local variable shadows struct member (`cs/local-shadows-struct-member`) | No results | The query has been replaced by the new query: Local scope variable shadows member (`cs/local-shadows-member`). |
| Missing Dispose call on local IDisposable (`cs/local-not-disposed`) | Fewer false positive results | The query identifies more cases where the local variable may be disposed by a library call. |
| Nested loops with same variable (`cs/nested-loops-with-same-variable`) | Fewer false positive results | Results are no longer highlighted in nested loops that share the same condition, and do not use the variable after the inner loop. |
| Null-coalescing left operand is constant (`cs/constant-null-coalescing`) | No results | The query has been removed, as alerts for this problem are now reported by the new query: Constant condition (`cs/constant-condition`). |
| Parameter shadows class member (`cs/parameter-shadows-class-member`) | No results | The query has been replaced by the new query: Local scope variable shadows member (`cs/local-shadows-member`). |
| Parameter shadows struct member (`cs/parameter-shadows-struct-member`) | No results | The query has been replaced by the new query: Local scope variable shadows member (`cs/local-shadows-member`). |
| Potentially incorrect CompareTo(...) signature (`cs/wrong-compareto-signature`) | Fewer false positive results | Results are no longer highlighted in constructed types. |
| Switch selector is constant (`cs/constant-switch-selector`) | No results | The query has been removed, as alerts for this problem are now reported by the new query: Constant condition (`cs/constant-condition`). |
| Useless upcast (`cs/useless-upcast`) | Fewer false positive results | The query has been improved to cover more cases where upcasts may be needed. |
## Changes to code extraction
* *Series of bullet points*
* The `into` part of `join` clauses is now extracted.
* The `when` part of constant cases is now extracted.
* Fixed a bug where `while(x is T y) ...` was not extracted correctly.
## Changes to QL libraries
* A new non-member predicate `mayBeDisposed()` can be used to determine if a variable is potentially disposed inside a library. It will analyse the CIL code in the library to determine this.
* A new non-member predicate `mayBeDisposed()` can be used to determine if a variable is potentially disposed inside a library. It will analyze the CIL code in the library to determine this.
* The predicate `getCondition()` has been moved from `TypeCase` to `CaseStmt`. It is now possible to get the condition of a `ConstCase` using its `getCondition()` predicate.
* Several control flow graph entities have been renamed (the old names are deprecated but are still available in this release for backwards compatibility):
- `ControlFlowNode` has been renamed to `ControlFlow::Node`.
- `CallableEntryNode` has been renamed to `ControlFlow::Nodes::EntryNode`.
- `CallableExitNode` has been renamed to `ControlFlow::Nodes::ExitNode`.
- `ControlFlowEdgeType` has been renamed to `ControlFlow::SuccessorType`.
- `ControlFlowEdgeSuccessor` has been renamed to `ControlFlow::SuccessorTypes::NormalSuccessor`.
- `ControlFlowEdgeConditional` has been renamed to `ControlFlow::SuccessorTypes::ConditionalSuccessor`.
- `ControlFlowEdgeBoolean` has been renamed to `ControlFlow::SuccessorTypes::BooleanSuccessor`.
- `ControlFlowEdgeNullness` has been renamed to `ControlFlow::SuccessorTypes::NullnessSuccessor`.
- `ControlFlowEdgeMatching` has been renamed to `ControlFlow::SuccessorTypes::MatchingSuccessor`.
- `ControlFlowEdgeEmptiness` has been renamed to `ControlFlow::SuccessorTypes::EmptinessSuccessor`.
- `ControlFlowEdgeReturn` has been renamed to `ControlFlow::SuccessorTypes::ReturnSuccessor`.
- `ControlFlowEdgeBreak` has been renamed to `ControlFlow::SuccessorTypes::BreakSuccessor`.
- `ControlFlowEdgeContinue` has been renamed to `ControlFlow::SuccessorTypes::ContinueSuccessor`.
- `ControlFlowEdgeGotoLabel` has been renamed to `ControlFlow::SuccessorTypes::GotoLabelSuccessor`.
- `ControlFlowEdgeGotoCase` has been renamed to `ControlFlow::SuccessorTypes::GotoCaseSuccessor`.
- `ControlFlowEdgeGotoDefault` has been renamed to `ControlFlow::SuccessorTypes::GotoDefaultSuccessor`.
- `ControlFlowEdgeException` has been renamed to `ControlFlow::SuccessorTypes::ExceptionSuccessor`.
> You should update any custom queries that use these entities to ensure that they continue working when the old names are removed in a future release.

View File

@@ -2,15 +2,13 @@
## General improvements
* Additional heuristics have been added to `semmle.javascript.heuristics`. Add `import semmle.javascript.heuristics.all` to a query in order to activate all of the heuristics at once.
* Improved modeling of data flow through destructuring assignments may give additional results for the security queries and other queries that rely on data flow.
* Modelling of data flow through destructuring assignments has been improved. This may give additional results for the security queries and other queries that rely on data flow.
* Improved modeling of global variables may give more true-positive results and fewer false-positive results for a variety of queries.
* Modelling of global variables has been improved. This may give more true-positive results and fewer false-positive results for a variety of queries.
* Improved modeling of re-export declarations may result in fewer false-positive results for a variety of queries.
* Modelling of re-export declarations has been improved. This may result in fewer false-positive results for a variety of queries.
* Modelling of taint flow through array operations has been improved. This may give additional results for the security queries.
* Improved modeling of taint flow through array operations may give additional results for the security queries.
* The taint tracking library recognizes more ways in which taint propagates. In particular, some flow through string formatters is now recognized. This may give additional results for the security queries.
@@ -18,74 +16,86 @@
* Type inference for simple function calls has been improved. This may give additional results for queries that rely on type inference.
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following libraries:
- [bluebird](https://bluebirdjs.com)
- [browserid-crypto](https://github.com/mozilla/browserid-crypto)
- [compose-function](https://github.com/stoeffel/compose-function)
- [cookie-parser](https://github.com/expressjs/cookie-parser)
- [cookie-session](https://github.com/expressjs/cookie-session)
- [crypto-js](https://github.com/https://github.com/brix/crypto-js)
- [deep-assign](https://github.com/sindresorhus/deep-assign)
- [deep-extend](https://github.com/unclechu/node-deep-extend)
- [deep-merge](https://github.com/Raynos/deep-merge)
- [deep](https://github.com/jeffomatic/deep)
- [deepmerge](https://github.com/KyleAMathews/deepmerge)
- [defaults-deep](https://github.com/jonschlinkert/defaults-deep)
- [defaults](https://github.com/tmpvar/defaults)
- [dottie](https://github.com/mickhansen/dottie.js)
- [dotty](https://github.com/deoxxa/dotty)
- [ent](https://github.com/substack/node-ent)
- [entities](https://github.com/fb55/node-entities)
- [escape-goat](https://github.com/sindresorhus/escape-goat)
- [express-jwt](https://github.com/auth0/express-jwt)
- [express-session](https://github.com/expressjs/session)
- [extend-shallow](https://github.com/jonschlinkert/extend-shallow)
- [extend](https://github.com/justmoon/node-extend)
- [extend2](https://github.com/eggjs/extend2)
- [fast-json-parse](https://github.com/mcollina/fast-json-parse)
- [forge](https://github.com/digitalbazaar/forge)
- [format-util](https://github.com/tmpfs/format-util)
- [global](https://github.com/Raynos/global)
- [he](https://github.com/mathiasbynens/he)
- [html-entities](https://github.com/mdevils/node-html-entities)
- [jquery](https://jquery.com)
- [js-extend](https://github.com/vmattos/js-extend)
- [json-parse-better-errors](https://github.com/zkat/json-parse-better-errors)
- [json-parse-safe](https://github.com/joaquimserafim/json-parse-safe)
- [json-safe-parse](https://github.com/bahamas10/node-json-safe-parse)
- [just-compose](https://github.com/angus-c/just)
- [just-extend](https://github.com/angus-c/just)
- [lodash](https://lodash.com)
- [merge-deep](https://github.com/jonschlinkert/merge-deep)
- [merge-options](https://github.com/schnittstabil/merge-options)
- [merge](https://github.com/yeikos/js.merge)
- [mixin-deep](https://github.com/jonschlinkert/mixin-deep)
- [mixin-object](https://github.com/jonschlinkert/mixin-object)
- [MySQL2](https://github.com/sidorares/node-mysql2)
- [node.extend](https://github.com/dreamerslab/node.extend)
- [object-assign](https://github.com/sindresorhus/object-assign)
- [object.assign](https://github.com/ljharb/object.assign)
- [object.defaults](https://github.com/jonschlinkert/object.defaults)
- [parse-json](https://github.com/sindresorhus/parse-json)
- [printf](https://github.com/adaltas/node-printf)
- [printj](https://github.com/SheetJS/printj)
- [q](https://documentup.com/kriskowal/q/)
- [ramda](https://ramdajs.com)
- [React Native](https://facebook.github.io/react-native/)
- [safe-json-parse](https://github.com/Raynos/safe-json-parse)
- [sanitize](https://github.com/pocketly/node-sanitize)
- [sanitizer](https://github.com/theSmaw/Caja-HTML-Sanitizer)
- [smart-extend](https://github.com/danielkalen/smart-extend)
- [sprintf.js](https://github.com/alexei/sprintf.js)
- [string-template](https://github.com/Matt-Esch/string-template)
- [underscore](https://underscorejs.org)
- [util-extend](https://github.com/isaacs/util-extend)
- [utils-merge](https://github.com/jaredhanson/utils-merge)
- [validator](https://github.com/chriso/validator.js)
- [xss](https://github.com/leizongmin/js-xss)
- [xtend](https://github.com/Raynos/xtend)
* Additional heuristics have been added to `semmle.javascript.heuristics`. Add `import semmle.javascript.heuristics.all` to a query in order to activate all of the heuristics at once.
* Handling of ambient TypeScript code has been improved. As a result, fewer false positives will be reported in `.d.ts` files.
* Handling of ambient TypeScript code has been improved. As a result, fewer false-positive results will be reported in `.d.ts` files.
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following libraries:
[axios](https://github.com/axios/axios),
[bluebird](https://bluebirdjs.com),
[browserid-crypto](https://github.com/mozilla/browserid-crypto),
[compose-function](https://github.com/stoeffel/compose-function),
[cookie-parser](https://github.com/expressjs/cookie-parser),
[cookie-session](https://github.com/expressjs/cookie-session),
[cross-fetch](https://github.com/lquixada/cross-fetch),
[crypto-js](https://github.com/https://github.com/brix/crypto-js),
[deep-assign](https://github.com/sindresorhus/deep-assign),
[deep-extend](https://github.com/unclechu/node-deep-extend),
[deep-merge](https://github.com/Raynos/deep-merge),
[deep](https://github.com/jeffomatic/deep),
[deepmerge](https://github.com/KyleAMathews/deepmerge),
[defaults-deep](https://github.com/jonschlinkert/defaults-deep),
[defaults](https://github.com/tmpvar/defaults),
[dottie](https://github.com/mickhansen/dottie.js),
[dotty](https://github.com/deoxxa/dotty),
[ent](https://github.com/substack/node-ent),
[entities](https://github.com/fb55/node-entities),
[escape-goat](https://github.com/sindresorhus/escape-goat),
[express-jwt](https://github.com/auth0/express-jwt),
[express-session](https://github.com/expressjs/session),
[extend-shallow](https://github.com/jonschlinkert/extend-shallow),
[extend](https://github.com/justmoon/node-extend),
[extend2](https://github.com/eggjs/extend2),
[fast-json-parse](https://github.com/mcollina/fast-json-parse),
[forge](https://github.com/digitalbazaar/forge),
[format-util](https://github.com/tmpfs/format-util),
[got](https://github.com/sindresorhus/got),
[global](https://github.com/Raynos/global),
[he](https://github.com/mathiasbynens/he),
[html-entities](https://github.com/mdevils/node-html-entities),
[isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch),
[jquery](https://jquery.com),
[js-extend](https://github.com/vmattos/js-extend),
[json-parse-better-errors](https://github.com/zkat/json-parse-better-errors),
[json-parse-safe](https://github.com/joaquimserafim/json-parse-safe),
[json-safe-parse](https://github.com/bahamas10/node-json-safe-parse),
[just-compose](https://github.com/angus-c/just),
[just-extend](https://github.com/angus-c/just),
[lodash](https://lodash.com),
[merge-deep](https://github.com/jonschlinkert/merge-deep),
[merge-options](https://github.com/schnittstabil/merge-options),
[merge](https://github.com/yeikos/js.merge),
[mixin-deep](https://github.com/jonschlinkert/mixin-deep),
[mixin-object](https://github.com/jonschlinkert/mixin-object),
[MySQL2](https://github.com/sidorares/node-mysql2),
[node.extend](https://github.com/dreamerslab/node.extend),
[node-fetch](https://github.com/bitinn/node-fetch),
[object-assign](https://github.com/sindresorhus/object-assign),
[object.assign](https://github.com/ljharb/object.assign),
[object.defaults](https://github.com/jonschlinkert/object.defaults),
[parse-json](https://github.com/sindresorhus/parse-json),
[printf](https://github.com/adaltas/node-printf),
[printj](https://github.com/SheetJS/printj),
[q](https://documentup.com/kriskowal/q/),
[ramda](https://ramdajs.com),
[request](https://github.com/request/request),
[request-promise](https://github.com/request/request-promise),
[request-promise-any](https://github.com/request/request-promise-any),
[request-promise-native](https://github.com/request/request-promise-native),
[React Native](https://facebook.github.io/react-native/),
[safe-json-parse](https://github.com/Raynos/safe-json-parse),
[sanitize](https://github.com/pocketly/node-sanitize),
[sanitizer](https://github.com/theSmaw/Caja-HTML-Sanitizer),
[smart-extend](https://github.com/danielkalen/smart-extend),
[sprintf.js](https://github.com/alexei/sprintf.js),
[string-template](https://github.com/Matt-Esch/string-template),
[superagent](https://github.com/visionmedia/superagent),
[underscore](https://underscorejs.org),
[util-extend](https://github.com/isaacs/util-extend),
[utils-merge](https://github.com/jaredhanson/utils-merge),
[validator](https://github.com/chriso/validator.js),
[xss](https://github.com/leizongmin/js-xss),
[xtend](https://github.com/Raynos/xtend).
## New queries
@@ -94,36 +104,36 @@
| Clear-text logging of sensitive information (`js/clear-text-logging`) | security, external/cwe/cwe-312, external/cwe/cwe-315, external/cwe/cwe-359 | Highlights logging of sensitive information, indicating a violation of [CWE-312](https://cwe.mitre.org/data/definitions/312.html). Results shown on LGTM by default. |
| Disabling Electron webSecurity (`js/disabling-electron-websecurity`) | security, frameworks/electron | Highlights Electron browser objects that are created with the `webSecurity` property set to false. Results shown on LGTM by default. |
| Enabling Electron allowRunningInsecureContent (`js/enabling-electron-insecure-content`) | security, frameworks/electron | Highlights Electron browser objects that are created with the `allowRunningInsecureContent` property set to true. Results shown on LGTM by default. |
| Uncontrolled data used in remote request (`js/request-forgery`) | security, external/cwe/cwe-918 | Highlights remote requests that are built from unsanitized user input, indicating a violation of [CWE-918](https://cwe.mitre.org/data/definitions/918.html). Results are hidden on LGTM by default. |
| Use of externally-controlled format string (`js/tainted-format-string`) | security, external/cwe/cwe-134 | Highlights format strings containing user-provided data, indicating a violation of [CWE-134](https://cwe.mitre.org/data/definitions/134.html). Results shown on LGTM by default. |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| Arguments redefined | Fewer results | This rule previously also flagged redefinitions of `eval`. This was an oversight that is now fixed. |
| Comparison between inconvertible types | Fewer results | This rule now flags fewer comparisons involving parameters. |
| Comparison between inconvertible types | Lower severity | The severity of this rule has been revised to "warning". |
| CORS misconfiguration for credentials transfer | More true-positive results | This rule now treats header names case-insensitively. |
| Hard-coded credentials | More true-positive results | This rule now recognizes secret cryptographic keys. |
| Incomplete string escaping or encoding | Better name, more true-positive results | This rule has been renamed to more clearly reflect its purpose. Also, it now recognizes incomplete URL encoding and decoding. |
| Insecure randomness | More true-positive results | This rule now recognizes secret cryptographic keys. |
| Missing rate limiting | More true-positive results, fewer false-positive results | This rule now recognizes additional rate limiters and expensive route handlers. |
| Missing X-Frame-Options HTTP header | Fewer false-positive results | This rule now treats header names case-insensitively. |
| Reflected cross-site scripting | Fewer false-positive results | This rule now treats header names case-insensitively. |
| Server-side URL redirect | More true-positive results | This rule now treats header names case-insensitively. |
| Superfluous trailing arguments | Fewer false-positive results | This rule now ignores calls to some empty functions. |
| Type confusion through parameter tampering | Fewer false-positive results | This rule no longer flags emptiness checks. |
| Uncontrolled command line | More true-positive results | This rule now recognizes indirect command injection through `sh -c` and similar. |
| Unused variable | Fewer results | This rule no longer flags class expressions that could be made anonymous. While technically true, these results are not interesting. |
| Unused variable | Renamed | This rule has been renamed to "Unused variable, import, function or class" to reflect the fact that it flags different kinds of unused program elements. |
| Use of incompletely initialized object| Fewer results | This rule now flags the constructor instead its errorneous `this` or `super` expressions. |
| Useless conditional | Fewer results | This rule no longer flags uses of boolean return values. |
| Useless conditional | Fewer results | This rule now flags fewer comparisons involving parameters. |
| Arguments redefined (`js/arguments-redefinition`) | Fewer results | This query previously also flagged redefinitions of `eval`. This was an oversight that is now fixed. |
| Comparison between inconvertible types (`js/comparison-between-incompatible-types`) | Fewer results | This query now flags fewer comparisons involving parameters. The severity of this query has been revised to "warning". |
| CORS misconfiguration for credentials transfer (`js/cors-misconfiguration-for-credentials`) | More true-positive results | This query now treats header names case-insensitively. |
| Hard-coded credentials (`js/hardcoded-credentials`) | More true-positive results | This query now recognizes secret cryptographic keys. |
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | New name, more true-positive results | The "Incomplete sanitization" query has been renamed to more clearly reflect its purpose. It now recognizes incomplete URL encoding and decoding. |
| Insecure randomness (`js/insecure-randomness`) | More true-positive results | This query now recognizes secret cryptographic keys. |
| Misleading indentation after control statement (`js/misleading-indentation-after-control-statement`) | Fewer results | This query temporarily ignores TypeScript files. |
| Missing rate limiting (`js/missing-rate-limiting`) | More true-positive results, fewer false-positive results | This query now recognizes additional rate limiters and expensive route handlers. |
| Omitted array element (`js/omitted-array-element`)| Fewer results | This query temporarily ignores TypeScript files. |
| Reflected cross-site scripting (`js/reflected-xss`) | Fewer false-positive results | This query now treats header names case-insensitively. |
| Semicolon insertion (`js/automatic-semicolon-insertion`) | Fewer results | This query temporarily ignores TypeScript files. |
| Server-side URL redirect (`js/server-side-unvalidated-url-redirection`) | More true-positive results | This query now treats header names case-insensitively. |
| Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer false-positive results | This query now ignores calls to some empty functions. |
| Type confusion through parameter tampering (`js/type-confusion-through-parameter-tampering`) | Fewer false-positive results | This query no longer flags emptiness checks. |
| Uncontrolled command line (`js/command-line-injection`) | More true-positive results | This query now recognizes indirect command injection through `sh -c` and similar. |
| Unused variable, import, function or class (`js/unused-local-variable`) | New name, fewer results | The "Unused variable" query has been renamed to reflect the fact that it highlights different kinds of unused program elements. In addition, the query no longer highlights class expressions that could be made anonymous. While technically true, these results are not interesting. |
| Use of incompletely initialized object (`js/incomplete-object-initialization`) | Fewer results | This query now highlights the constructor instead of its erroneous `this` or `super` expressions. |
| Useless conditional (`js/trivial-conditional`) | Fewer results | This query no longer flags uses of boolean return values and highlights fewer comparisons involving parameters. |
## Changes to QL libraries
* HTTP and HTTPS requests made using the Node.js `http.request` and `https.request` APIs and the Electron `Electron.net.request` and `Electron.ClientRequest` APIs are modeled as `RemoteFlowSources`.
* HTTP header names are now always normalized to lower case to reflect the fact that they are case insensitive. In particular, the result of `HeaderDefinition.getAHeaderName`, and the first parameter of `HeaderDefinition.defines`, `ExplicitHeaderDefinition.definesExplicitly` and `RouteHandler.getAResponseHeader` is now always a lower-case string.
* HTTP and HTTPS requests made using the Node.js `http.request` and `https.request` APIs, and the Electron `Electron.net.request` and `Electron.ClientRequest` APIs, are modeled as `RemoteFlowSources`.
* HTTP header names are now always normalized to lower case to reflect the fact that they are case insensitive. In particular, the result of `HeaderDefinition.getAHeaderName`, and the first parameter of `HeaderDefinition.defines`, `ExplicitHeaderDefinition.definesExplicitly`, and `RouteHandler.getAResponseHeader` are now always a lower-case string.
* New AST nodes have been added for TypeScript 2.9 and 3.0 features.
* The class `JsonParseCall` has been deprecated. Use `JsonParserCall` instead.
* The class `JsonParseCall` has been deprecated. Update your queries to use `JsonParserCall` instead.
* The handling of spread arguments in the data flow library has been changed: `DataFlow::InvokeNode.getArgument(i)` is now only defined when there is no spread argument at or before argument position `i`, and similarly `InvokeNode.getNumArgument` is only defined for invocations without spread arguments.

View File

@@ -602,7 +602,7 @@ class ReturnValueInstruction extends ReturnInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof ReturnValueOperand and
exists(this.getOperand(tag.(ReturnValueOperand))) and
result instanceof IndirectMemoryAccess
}
}
@@ -629,7 +629,7 @@ class LoadInstruction extends CopyInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof CopySourceOperand and
exists(this.getOperand(tag.(CopySourceOperand))) and
result instanceof IndirectMemoryAccess
}
@@ -1015,7 +1015,7 @@ class ThrowValueInstruction extends ThrowInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof ExceptionOperand and
exists(this.getOperand(tag.(ExceptionOperand))) and
result instanceof IndirectMemoryAccess
}
@@ -1114,7 +1114,7 @@ class UnmodeledUseInstruction extends Instruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof UnmodeledUseOperand and
exists(this.getOperand(tag.(UnmodeledUseOperand))) and
result instanceof UnmodeledMemoryAccess
}
}
@@ -1125,7 +1125,7 @@ class PhiInstruction extends Instruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof PhiOperand and
exists(this.getOperand(tag.(PhiOperand))) and
result instanceof PhiMemoryAccess
}

View File

@@ -602,7 +602,7 @@ class ReturnValueInstruction extends ReturnInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof ReturnValueOperand and
exists(this.getOperand(tag.(ReturnValueOperand))) and
result instanceof IndirectMemoryAccess
}
}
@@ -629,7 +629,7 @@ class LoadInstruction extends CopyInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof CopySourceOperand and
exists(this.getOperand(tag.(CopySourceOperand))) and
result instanceof IndirectMemoryAccess
}
@@ -1015,7 +1015,7 @@ class ThrowValueInstruction extends ThrowInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof ExceptionOperand and
exists(this.getOperand(tag.(ExceptionOperand))) and
result instanceof IndirectMemoryAccess
}
@@ -1114,7 +1114,7 @@ class UnmodeledUseInstruction extends Instruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof UnmodeledUseOperand and
exists(this.getOperand(tag.(UnmodeledUseOperand))) and
result instanceof UnmodeledMemoryAccess
}
}
@@ -1125,7 +1125,7 @@ class PhiInstruction extends Instruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof PhiOperand and
exists(this.getOperand(tag.(PhiOperand))) and
result instanceof PhiMemoryAccess
}

View File

@@ -602,7 +602,7 @@ class ReturnValueInstruction extends ReturnInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof ReturnValueOperand and
exists(this.getOperand(tag.(ReturnValueOperand))) and
result instanceof IndirectMemoryAccess
}
}
@@ -629,7 +629,7 @@ class LoadInstruction extends CopyInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof CopySourceOperand and
exists(this.getOperand(tag.(CopySourceOperand))) and
result instanceof IndirectMemoryAccess
}
@@ -1015,7 +1015,7 @@ class ThrowValueInstruction extends ThrowInstruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof ExceptionOperand and
exists(this.getOperand(tag.(ExceptionOperand))) and
result instanceof IndirectMemoryAccess
}
@@ -1114,7 +1114,7 @@ class UnmodeledUseInstruction extends Instruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof UnmodeledUseOperand and
exists(this.getOperand(tag.(UnmodeledUseOperand))) and
result instanceof UnmodeledMemoryAccess
}
}
@@ -1125,7 +1125,7 @@ class PhiInstruction extends Instruction {
}
override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) {
tag instanceof PhiOperand and
exists(this.getOperand(tag.(PhiOperand))) and
result instanceof PhiMemoryAccess
}

View File

@@ -5,7 +5,7 @@ private import semmle.code.csharp.frameworks.system.web.UI
class DisposableType extends RefType {
DisposableType() {
this.getABaseType+() = getSystemIDisposableInterface()
this.getABaseType+() instanceof SystemIDisposableInterface
}
}
@@ -17,13 +17,13 @@ class DisposableField extends Field {
class WebControl extends RefType {
WebControl() {
this.getBaseClass*() = getSystemWebUIControlClass()
this.getBaseClass*() instanceof SystemWebUIControlClass
}
}
class WebPage extends RefType {
WebPage() {
this.getBaseClass*() = getSystemWebUIPageClass()
this.getBaseClass*() instanceof SystemWebUIPageClass
}
}

View File

@@ -14,7 +14,6 @@
import csharp
import semmle.code.csharp.commons.Assertions
import semmle.code.csharp.commons.Constants
import ControlFlowGraph
/** A constant condition. */
abstract class ConstantCondition extends Expr {
@@ -76,13 +75,13 @@ class ConstantNullnessCondition extends ConstantCondition {
boolean b;
ConstantNullnessCondition() {
forex(ControlFlowNode cfn |
forex(ControlFlow::Node cfn |
cfn = this.getAControlFlowNode() |
exists(ControlFlowEdgeNullness t |
exists(ControlFlow::SuccessorTypes::NullnessSuccessor t |
exists(cfn.getASuccessorByType(t)) |
if t.isNull() then b = true else b = false
) and
strictcount(ControlFlowEdgeType t | exists(cfn.getASuccessorByType(t))) = 1
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
)
}
@@ -99,13 +98,13 @@ class ConstantMatchingCondition extends ConstantCondition {
boolean b;
ConstantMatchingCondition() {
forex(ControlFlowNode cfn |
forex(ControlFlow::Node cfn |
cfn = this.getAControlFlowNode() |
exists(ControlFlowEdgeMatching t |
exists(ControlFlow::SuccessorTypes::MatchingSuccessor t |
exists(cfn.getASuccessorByType(t)) |
if t.isMatch() then b = true else b = false
) and
strictcount(ControlFlowEdgeType t | exists(cfn.getASuccessorByType(t))) = 1
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
)
}

View File

@@ -35,5 +35,5 @@ class StringComparison extends Expr {
from StringComparison sc, PropertyAccess pa
where sc.getAnOperand() instanceof StringLiteral
and sc.getAnOperand() = pa
and pa.getTarget() = getSystemTypeClass().getFullNameProperty()
and pa.getTarget() = any(SystemTypeClass c).getFullNameProperty()
select sc, "Erroneous class compare."

View File

@@ -102,17 +102,17 @@ class LockStmtBlock extends LockedBlock
exists( LockStmt s | this=s.getBlock() )
}
predicate isLockThis()
override predicate isLockThis()
{
exists( LockStmt s | this=s.getBlock() and s.isLockThis() )
}
Variable getLockVariable()
override Variable getLockVariable()
{
exists( LockStmt s | this=s.getBlock() and result=s.getLockVariable() )
}
Type getLockTypeObject()
override Type getLockTypeObject()
{
exists( LockStmt s | this=s.getBlock() and result=s.getLockTypeObject() )
}
@@ -138,17 +138,17 @@ class SynchronizedMethodBlock extends LockedBlock
{
exists( SynchronizedMethod m | this=m.getStatementBody() )
}
predicate isLockThis()
override predicate isLockThis()
{
exists( SynchronizedMethod m | this=m.getStatementBody() and m.isLockThis() )
}
Variable getLockVariable()
override Variable getLockVariable()
{
none()
}
Type getLockTypeObject()
override Type getLockTypeObject()
{
exists( SynchronizedMethod m | this=m.getStatementBody() and result=m.getLockTypeObject() )
}

View File

@@ -13,7 +13,6 @@
import csharp
import DataMembers
import ThreadCreation
import ControlFlowGraph
predicate correctlySynchronized(CollectionMember c, Expr access) {
access = c.getAReadOrWrite() and
@@ -24,9 +23,9 @@ predicate correctlySynchronized(CollectionMember c, Expr access) {
)
}
ControlFlowNode unlockedReachable(Callable a) {
ControlFlow::Node unlockedReachable(Callable a) {
result = a.getEntryPoint() or
exists(ControlFlowNode mid | mid = unlockedReachable(a) |
exists(ControlFlow::Node mid | mid = unlockedReachable(a) |
not mid.getElement() instanceof LockingCall and
result = mid.getASuccessor()
)

View File

@@ -13,7 +13,6 @@
import csharp
import semmle.code.csharp.commons.ComparisonTest
import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlowGraph
import semmle.code.csharp.commons.StructuralComparison as SC
/** A structural comparison configuration for comparing the conditions of nested `for` loops. */
@@ -87,13 +86,13 @@ class NestedForLoopSameVariable extends ForStmt {
}
/** Finds elements inside the outer loop that are no longer guarded by the loop invariant. */
private ControlFlowNode getAnUnguardedNode()
private ControlFlow::Node getAnUnguardedNode()
{
result.getElement().getParent+() = getOuterForStmt().getBody() and
(
result = this.getCondition().(ControlFlowElement).getAControlFlowExitNode().getAFalseSuccessor()
or
exists(ControlFlowNode mid | mid = getAnUnguardedNode() |
exists(ControlFlow::Node mid | mid = getAnUnguardedNode() |
mid.getASuccessor() = result and
not exists(getAComparisonTest(result.getElement()))
)

View File

@@ -14,7 +14,7 @@
import csharp
// Iterate the control flow until we reach a Stmt
Stmt findSuccessorStmt(ControlFlowGraph::ControlFlowNode n)
Stmt findSuccessorStmt(ControlFlow::Node n)
{
result=n.getElement() or
not n.getElement() instanceof Stmt and result=findSuccessorStmt(n.getASuccessor())

View File

@@ -12,11 +12,11 @@
import csharp
import semmle.code.csharp.frameworks.System
predicate nodeBeforeParameterAccess(ControlFlowGraph::ControlFlowNode node)
predicate nodeBeforeParameterAccess(ControlFlow::Node node)
{
exists(EqualsMethod equals | equals.getBody() = node.getElement())
or
exists(EqualsMethod equals, Parameter param, ControlFlowGraph::ControlFlowNode mid |
exists(EqualsMethod equals, Parameter param, ControlFlow::Node mid |
equals.getParameter(0) = param and
equals.getAChild*() = mid.getElement() and
nodeBeforeParameterAccess(mid) and

View File

@@ -11,7 +11,7 @@
import csharp
import semmle.code.csharp.frameworks.system.Text
from ObjectCreation creation, LoopStmt loop, ControlFlowGraph::ControlFlowNode loopEntryNode
from ObjectCreation creation, LoopStmt loop, ControlFlow::Node loopEntryNode
where creation.getType() instanceof SystemTextStringBuilderClass
and loopEntryNode = loop.getBody().getAControlFlowEntryNode()
and loop.getBody().getAChild*() = creation

View File

@@ -12,10 +12,9 @@
*/
import csharp
import ControlFlowGraph
import semmle.code.csharp.frameworks.system.web.Security
predicate loginMethod(Method m, ControlFlowEdgeType flowFrom)
predicate loginMethod(Method m, ControlFlow::SuccessorType flowFrom)
{
(
m = any(SystemWebSecurityMembershipClass c).getValidateUserMethod()
@@ -23,11 +22,11 @@ predicate loginMethod(Method m, ControlFlowEdgeType flowFrom)
m = any(SystemWebSecurityFormsAuthenticationClass c).getAuthenticateMethod()
)
and
flowFrom.(ControlFlowEdgeBoolean).getValue()=true
flowFrom.(ControlFlow::SuccessorTypes::BooleanSuccessor).getValue()=true
or
m = any(SystemWebSecurityFormsAuthenticationClass c).getSignOutMethod()
and
flowFrom instanceof ControlFlowEdgeSuccessor
flowFrom instanceof ControlFlow::SuccessorTypes::NormalSuccessor
}
/** The `System.Web.SessionState.HttpSessionState` class. */
@@ -62,14 +61,14 @@ predicate sessionUse(MemberAccess ma)
}
/** A control flow step that is not sanitised by a call to clear the session. */
predicate controlStep(ControlFlowNode s1, ControlFlowNode s2)
predicate controlStep(ControlFlow::Node s1, ControlFlow::Node s2)
{
s2 = s1.getASuccessor()
and
not sessionEndMethod(s2.getElement().(MethodCall).getTarget())
}
from ControlFlowNode loginCall, Method loginMethod, ControlFlowNode sessionUse, ControlFlowEdgeType fromLoginFlow
from ControlFlow::Node loginCall, Method loginMethod, ControlFlow::Node sessionUse, ControlFlow::SuccessorType fromLoginFlow
where loginMethod = loginCall.getElement().(MethodCall).getTarget()
and loginMethod(loginMethod, fromLoginFlow)
and sessionUse(sessionUse.getElement())

View File

@@ -29,11 +29,18 @@ import semmle.code.csharp.exprs.Dynamic
import semmle.code.csharp.exprs.Expr
import semmle.code.csharp.exprs.Literal
import semmle.code.csharp.exprs.LogicalOperation
import semmle.code.csharp.controlflow.ControlFlowGraph as ControlFlowGraph
import semmle.code.csharp.controlflow.ControlFlowGraph
import semmle.code.csharp.dataflow.DataFlow
import semmle.code.csharp.dataflow.TaintTracking
import semmle.code.csharp.dataflow.SSA
/** DEPRECATED: Use `ControlFlow` instead. */
deprecated
module ControlFlowGraph {
import semmle.code.csharp.controlflow.ControlFlowGraph
import ControlFlow
}
/** Whether the source was extracted without a build command. */
predicate extractionIsStandalone() {
exists(SourceFile f | f.extractedStandalone())

View File

@@ -9,7 +9,7 @@ class ExternalDefect extends @externalDefect, Element {
float getSeverity() { externalDefects(this, _, _, _, result) }
Location getLocation() { externalDefects(this,_,result,_,_) }
override Location getLocation() { externalDefects(this,_,result,_,_) }
override string toString() {
result = getQueryPath() + ": " + getLocation() + " - " + getMessage()
@@ -22,7 +22,7 @@ class ExternalMetric extends @externalMetric, Element {
float getValue() { externalMetrics(this, _, _, result) }
Location getLocation() { externalMetrics(this,_,result,_) }
override Location getLocation() { externalMetrics(this,_,result,_) }
override string toString() {
result = getQueryPath() + ": " + getLocation() + " - " + getValue()

View File

@@ -3,7 +3,6 @@
*/
import csharp
private import ControlFlowGraph
/**
* An assignable, that is, an element that can be assigned to. Either a
@@ -348,7 +347,7 @@ private cached module AssignableDefinitionImpl {
cached predicate isUncertainRefCall(Call c, AssignableAccess aa) {
isRelevantRefCall(c, aa)
and
exists(ControlFlowGraph::BasicBlock bb, Parameter p |
exists(ControlFlow::BasicBlock bb, Parameter p |
isAnalyzableRefCall(c, aa, p) |
parameterReachesWithoutDef(p, bb) and
bb.getLastNode() = p.getCallable().getExitPoint()
@@ -360,14 +359,14 @@ private cached module AssignableDefinitionImpl {
* entry point of `p`'s callable to basic block `bb` without passing through
* any assignments to `p`.
*/
private predicate parameterReachesWithoutDef(Parameter p, BasicBlock bb) {
private predicate parameterReachesWithoutDef(Parameter p, ControlFlow::BasicBlock bb) {
not basicBlockRefParamDef(bb, p)
and
(
isAnalyzableRefCall(_, _, p) and
p.getCallable().getEntryPoint() = bb.getFirstNode()
or
exists(BasicBlock mid |
exists(ControlFlow::BasicBlock mid |
parameterReachesWithoutDef(p, mid) |
bb = mid.getASuccessor()
)
@@ -375,7 +374,7 @@ private cached module AssignableDefinitionImpl {
}
/** Holds if a node in basic block `bb` assigns to `ref` parameter `p`. */
private predicate basicBlockRefParamDef(BasicBlock bb, Parameter p) {
private predicate basicBlockRefParamDef(ControlFlow::BasicBlock bb, Parameter p) {
bb.getANode() = getAnAnalyzableRefDef(_, _, p).getAControlFlowNode()
}
@@ -447,11 +446,11 @@ class AssignableDefinition extends TAssignableDefinition {
* the definitions of `x` and `y` in `M(out x, out y)` and `(x, y) = (0, 1)`
* relate to the same call to `M` and assignment node, respectively.
*/
ControlFlowNode getAControlFlowNode() { none() }
ControlFlow::Node getAControlFlowNode() { none() }
/** DEPRECATED: Use `getAControlFlowNode()` instead. */
deprecated
ControlFlowNode getControlFlowNode() { result = this.getAControlFlowNode() }
ControlFlow::Node getControlFlowNode() { result = this.getAControlFlowNode() }
/** Gets the enclosing callable of this definition. */
Callable getEnclosingCallable() {
@@ -603,7 +602,7 @@ module AssignableDefinitions {
result = a
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = a.getAControlFlowNode()
}
@@ -644,7 +643,7 @@ module AssignableDefinitions {
* orders of the definitions of `x`, `y`, and `z` are 0, 1, and 2, respectively.
*/
int getEvaluationOrder() {
exists(BasicBlock bb, int i |
exists(ControlFlow::BasicBlock bb, int i |
bb.getNode(i).getElement() = leaf |
i = rank[result + 1](int j, TupleAssignmentDefinition def |
bb.getNode(j).getElement() = def.getLeaf() and
@@ -655,7 +654,7 @@ module AssignableDefinitions {
)
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = ae.getAControlFlowNode()
}
@@ -690,7 +689,7 @@ module AssignableDefinitions {
* the definitions of `x` and `y` are 0 and 1, respectively.
*/
int getIndex() {
exists(BasicBlock bb, int i |
exists(ControlFlow::BasicBlock bb, int i |
bb.getNode(i).getElement() = aa |
i = rank[result + 1](int j, OutRefDefinition def |
bb.getNode(j).getElement() = def.getTargetAccess() and
@@ -701,7 +700,7 @@ module AssignableDefinitions {
)
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = this.getCall().getAControlFlowNode()
}
@@ -733,7 +732,7 @@ module AssignableDefinitions {
result = mo
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = mo.getAControlFlowNode()
}
@@ -757,7 +756,7 @@ module AssignableDefinitions {
result = lvde
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = lvde.getAControlFlowNode()
}
@@ -782,7 +781,7 @@ module AssignableDefinitions {
result = p
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = p.getCallable().getEntryPoint()
}
@@ -810,7 +809,7 @@ module AssignableDefinitions {
result = aoe
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = aoe.getAControlFlowNode()
}
@@ -834,7 +833,7 @@ module AssignableDefinitions {
result = ipe.getVariableDeclExpr()
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = this.getDeclaration().getAControlFlowNode()
}
@@ -871,7 +870,7 @@ module AssignableDefinitions {
result = tc.getVariableDeclExpr()
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = this.getDeclaration().getAControlFlowNode()
}
@@ -907,7 +906,7 @@ module AssignableDefinitions {
result = a
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
none() // initializers are currently not part of the CFG
}

View File

@@ -167,12 +167,12 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
final predicate hasExpressionBody() { exists(getExpressionBody()) }
/** Gets the entry point in the control graph for this callable. */
ControlFlowGraph::CallableEntryNode getEntryPoint() {
ControlFlow::Nodes::EntryNode getEntryPoint() {
result.getCallable() = this
}
/** Gets the exit point in the control graph for this callable. */
ControlFlowGraph::CallableExitNode getExitPoint() {
ControlFlow::Nodes::ExitNode getExitPoint() {
result.getCallable() = this
}

View File

@@ -92,8 +92,7 @@ class EventAccessor extends Accessor, @event_accessor {
result instanceof VoidType
}
/** Gets the assembly name of this event accessor. */
string getAssemblyName() { event_accessors(this,_,result,_,_) }
override string getAssemblyName() { event_accessors(this,_,result,_,_) }
override EventAccessor getSourceDeclaration() { event_accessors(this,_,_,_,result) }

View File

@@ -250,7 +250,25 @@ class SwitchStmt extends SelectionStmt, @switch_stmt {
* A `case` statement. Either a constant case (`ConstCase`), a type matching
* case (`TypeCase`), or a `default` case (`DefaultCase`).
*/
class CaseStmt extends Stmt, @case { }
class CaseStmt extends Stmt, @case {
/**
* Gets the condition on this case, if any. For example, the type case on line 3
* has no condition, and the type case on line 4 has condition `s.Length > 0`, in
*
* ```
* switch(p)
* {
* case int i:
* case string s when s.Length > 0:
* break;
* ...
* }
* ```
*/
Expr getCondition() {
result = this.getChild(2)
}
}
/**
* A constant case of a `switch` statement, for example `case OpCode.Nop:`
@@ -280,15 +298,16 @@ class ConstCase extends LabeledStmt, CaseStmt {
}
/**
* A type matching case in a `switch` statement, for example `case int i:` on line 2 or
* `case string s when s.Length>0:` on line 3 in
* A type matching case in a `switch` statement, for example `case int i:` on line 3 or
* `case string s when s.Length > 0:` on line 4 in
*
* ```
* switch(p) {
* case int i:
* case string s when s.Length>0:
* break;
* ...
* switch(p)
* {
* case int i:
* case string s when s.Length > 0:
* break;
* ...
* }
* ```
*/
@@ -350,23 +369,6 @@ class TypeCase extends LabeledStmt, CaseStmt {
result = getTypeAccess().getType()
}
/**
* Gets the condition on this case, if any. For example, the type case on line 2
* has no condition, and the type case on line 3 has condition `s.Length>0`, in
*
* ```
* switch(p) {
* case int i:
* case string s when s.Length>0:
* break;
* ...
* }
* ```
*/
Expr getCondition() {
result = getChild(2)
}
override string toString() {
exists(string var |
if exists(this.getVariableDeclExpr()) then

View File

@@ -29,7 +29,7 @@ abstract class AssertNonNullMethod extends AssertMethod {
*/
class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod {
SystemDiagnosticsDebugAssertTrueMethod() {
this = getSystemDiagnosticsDebugClass().getAssertMethod()
this = any(SystemDiagnosticsDebugClass c).getAssertMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -38,7 +38,7 @@ class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod {
/** A Visual Studio assertion method. */
class VSTestAssertTrueMethod extends AssertTrueMethod {
VSTestAssertTrueMethod() {
this = getVSTestAssertClass().getIsTrueMethod()
this = any(VSTestAssertClass c).getIsTrueMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -47,7 +47,7 @@ class VSTestAssertTrueMethod extends AssertTrueMethod {
/** A Visual Studio negated assertion method. */
class VSTestAssertFalseMethod extends AssertFalseMethod {
VSTestAssertFalseMethod() {
this = getVSTestAssertClass().getIsFalseMethod()
this = any(VSTestAssertClass c).getIsFalseMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -56,7 +56,7 @@ class VSTestAssertFalseMethod extends AssertFalseMethod {
/** A Visual Studio `null` assertion method. */
class VSTestAssertNullMethod extends AssertNullMethod {
VSTestAssertNullMethod() {
this = getVSTestAssertClass().getIsNullMethod()
this = any(VSTestAssertClass c).getIsNullMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -65,7 +65,7 @@ class VSTestAssertNullMethod extends AssertNullMethod {
/** A Visual Studio non-`null` assertion method. */
class VSTestAssertNonNullMethod extends AssertNonNullMethod {
VSTestAssertNonNullMethod() {
this = getVSTestAssertClass().getIsNotNullMethod()
this = any(VSTestAssertClass c).getIsNotNullMethod()
}
override int getAssertionIndex() { result = 0 }

View File

@@ -40,7 +40,7 @@ module SsaChecks {
import Ssa
predicate nonUniqueSsaDef(AssignableRead read, string m) {
exists(ControlFlowNode cfn |
exists(ControlFlow::Node cfn |
strictcount(Definition def | def.getAReadAtNode(cfn) = read) > 1
)
and
@@ -48,7 +48,7 @@ module SsaChecks {
}
predicate notDominatedByDef(AssignableRead read, string m) {
exists(Definition def, BasicBlock bb, ControlFlowNode rnode, ControlFlowNode dnode, int i |
exists(Definition def, BasicBlock bb, ControlFlow::Node rnode, ControlFlow::Node dnode, int i |
def.getAReadAtNode(rnode) = read |
def.definesAt(bb, i) and
dnode = bb.getNode(max(int j | j = i or j = 0)) and
@@ -82,12 +82,10 @@ module SsaChecks {
}
module CfgChecks {
import ControlFlowGraph
predicate multipleSuccessors(ControlFlowElement cfe, string m) {
exists(ControlFlowNode cfn |
exists(ControlFlow::Node cfn |
cfn = cfe.getAControlFlowNode() |
strictcount(cfn.getASuccessorByType(any(ControlFlowEdgeSuccessor e))) > 1 and
strictcount(cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::NormalSuccessor e))) > 1 and
m = "Multiple (non-conditional/exceptional) successors"
)
}

View File

@@ -1,6 +1,5 @@
/** Provides logic for determining constant expressions. */
import csharp
private import ControlFlowGraph
private import semmle.code.csharp.commons.ComparisonTest
private import semmle.code.csharp.commons.StructuralComparison as StructuralComparison
@@ -8,10 +7,10 @@ private import semmle.code.csharp.commons.StructuralComparison as StructuralComp
* Holds if `e` is a condition that always evaluates to Boolean value `b`.
*/
predicate isConstantCondition(Expr e, boolean b) {
forex(ControlFlowNode cfn |
forex(ControlFlow::Node cfn |
cfn = e.getAControlFlowNode() |
exists(cfn.getASuccessorByType(any(ControlFlowEdgeBoolean t | t.getValue() = b))) and
strictcount(ControlFlowEdgeType t | exists(cfn.getASuccessorByType(t))) = 1
exists(cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::BooleanSuccessor t | t.getValue() = b))) and
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
)
}

View File

@@ -99,20 +99,20 @@ class BasicBlock extends TBasicBlockStart {
}
/** Gets the control flow node at a specific (zero-indexed) position in this basic block. */
ControlFlowGraph::ControlFlowNode getNode(int pos) { bbIndex(getFirstNode(), result, pos) }
ControlFlow::Node getNode(int pos) { bbIndex(getFirstNode(), result, pos) }
/** Gets a control flow node in this basic block. */
ControlFlowGraph::ControlFlowNode getANode() {
ControlFlow::Node getANode() {
result = getNode(_)
}
/** Gets the first control flow node in this basic block. */
ControlFlowGraph::ControlFlowNode getFirstNode() {
ControlFlow::Node getFirstNode() {
this = TBasicBlockStart(result)
}
/** Gets the last control flow node in this basic block. */
ControlFlowGraph::ControlFlowNode getLastNode() {
ControlFlow::Node getLastNode() {
result = getNode(length() - 1)
}
@@ -326,22 +326,22 @@ class BasicBlock extends TBasicBlockStart {
private cached module Internal {
/** Internal representation of basic blocks. */
cached newtype TBasicBlock =
TBasicBlockStart(ControlFlowGraph::ControlFlowNode cfn) { startsBB(cfn) }
TBasicBlockStart(ControlFlow::Node cfn) { startsBB(cfn) }
/** Holds if `cfn` starts a new basic block. */
private predicate startsBB(ControlFlowGraph::ControlFlowNode cfn) {
private predicate startsBB(ControlFlow::Node cfn) {
not exists(cfn.getAPredecessor()) and exists(cfn.getASuccessor())
or
cfn.isJoin()
or
exists(ControlFlowGraph::ControlFlowNode pred | pred = cfn.getAPredecessor() | strictcount(pred.getASuccessor()) > 1)
exists(ControlFlow::Node pred | pred = cfn.getAPredecessor() | strictcount(pred.getASuccessor()) > 1)
}
/**
* Holds if `succ` is a control flow successor of `pred` within
* the same basic block.
*/
private predicate intraBBSucc(ControlFlowGraph::ControlFlowNode pred, ControlFlowGraph::ControlFlowNode succ) {
private predicate intraBBSucc(ControlFlow::Node pred, ControlFlow::Node succ) {
succ = pred.getASuccessor() and
not startsBB(succ)
}
@@ -353,7 +353,7 @@ private cached module Internal {
* that starts a basic block to `cfn` along the `intraBBSucc` relation.
*/
cached
predicate bbIndex(ControlFlowGraph::ControlFlowNode bbStart, ControlFlowGraph::ControlFlowNode cfn, int i) =
predicate bbIndex(ControlFlow::Node bbStart, ControlFlow::Node cfn, int i) =
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
/**
@@ -395,7 +395,7 @@ class EntryBasicBlock extends BasicBlock {
/** Holds if `bb` is an entry basic block. */
private predicate entryBB(BasicBlock bb) {
bb.getFirstNode() instanceof ControlFlowGraph::CallableEntryNode
bb.getFirstNode() instanceof ControlFlow::Nodes::EntryNode
}
/**
@@ -408,7 +408,7 @@ class ExitBasicBlock extends BasicBlock {
/** Holds if `bb` is an exit basic block. */
private predicate exitBB(BasicBlock bb) {
bb.getLastNode() instanceof ControlFlowGraph::CallableExitNode
bb.getLastNode() instanceof ControlFlow::Nodes::ExitNode
}
/**

View File

@@ -309,8 +309,8 @@ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent)
isBooleanCompletionForParent = false
)
or
exists(TypeCase tc |
tc.getCondition() = e |
exists(CaseStmt cs |
cs.getCondition() = e |
isBooleanCompletionForParent = false
)
or

View File

@@ -7,12 +7,10 @@ private import semmle.code.csharp.ExprOrStmtParent
* A program element that can possess control flow. That is, either a statement or
* an expression.
*
* A control flow element can be mapped to a control flow node (`ControlFlowNode`)
* A control flow element can be mapped to a control flow node (`ControlFlow::Node`)
* via `getAControlFlowNode()`. There is a one-to-many relationship between
* `ControlFlowElement`s and `ControlFlowNode`s. This allows control flow
* control flow elements and control flow nodes. This allows control flow
* splitting, for example modeling the control flow through `finally` blocks.
*
* `ControlFlowNode`s are nodes in the control flow graph.
*/
class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
/** Gets the enclosing callable of this element, if any. */
@@ -22,26 +20,26 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
* Gets a control flow node for this element. That is, a node in the
* control flow graph that corresponds to this element.
*
* Typically, there is exactly one `ControlFlowNode` associated with a
* Typically, there is exactly one `ControlFlow::Node` associated with a
* `ControlFlowElement`, but a `ControlFlowElement` may be split into
* several `ControlFlowNode`s, for example to represent the continuation
* several `ControlFlow::Node`s, for example to represent the continuation
* flow in a `try/catch/finally` construction.
*/
ControlFlowGraph::ControlFlowNode getAControlFlowNode() {
ControlFlow::Node getAControlFlowNode() {
result.getElement() = this
}
/**
* Gets a first control flow node executed within this element.
*/
ControlFlowGraph::ControlFlowNode getAControlFlowEntryNode() {
ControlFlow::Node getAControlFlowEntryNode() {
result = ControlFlowGraph::Internal::getAControlFlowEntryNode(this).getAControlFlowNode()
}
/**
* Gets a potential last control flow node executed within this element.
*/
ControlFlowGraph::ControlFlowNode getAControlFlowExitNode() {
ControlFlow::Node getAControlFlowExitNode() {
result = ControlFlowGraph::Internal::getAControlFlowExitNode(this).getAControlFlowNode()
}
@@ -61,7 +59,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
/** Gets an element that is reachable from this element. */
ControlFlowElement getAReachableElement() {
// Reachable in same basic block
exists(ControlFlowGraph::BasicBlock bb, int i, int j |
exists(ControlFlow::BasicBlock bb, int i, int j |
bb.getNode(i) = getAControlFlowNode() and
bb.getNode(j) = result.getAControlFlowNode() and
i < j

View File

@@ -184,7 +184,7 @@ class NullGuardedExpr extends AccessOrCallExpr {
// Call to `string.IsNullOrEmpty()`
exists(MethodCall mc |
mc = cond and
mc.getTarget() = getSystemStringClass().getIsNullOrEmptyMethod() and
mc.getTarget() = any(SystemStringClass c).getIsNullOrEmptyMethod() and
mc.getArgument(0) = sub and
b = false
)

View File

@@ -18,12 +18,10 @@
*/
import csharp
private import ControlFlowGraph
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.commons.ComparisonTest
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.dataflow.SSA
private import semmle.code.csharp.controlflow.ControlFlowGraph
private import semmle.code.csharp.frameworks.System
/** An expression that may be `null`. */
@@ -412,7 +410,7 @@ private Expr failureIsNonNullTest(LocalScopeVariable var) {
* Gets an immediate successor node of the conditional node `cfgnode` where
* the condition implies that the variable `var` is `null`.
*/
private ControlFlowNode nullBranchKill(LocalScopeVariable var, ControlFlowNode cfgnode) {
private ControlFlow::Node nullBranchKill(LocalScopeVariable var, ControlFlow::Node cfgnode) {
(cfgnode.getElement() = nullTest(var) and result = cfgnode.getATrueSuccessor())
or
(cfgnode.getElement() = failureIsNullTest(var) and result = cfgnode.getAFalseSuccessor())
@@ -422,17 +420,17 @@ private ControlFlowNode nullBranchKill(LocalScopeVariable var, ControlFlowNode c
* Gets an immediate successor node of the conditional node `cfgnode` where
* the condition implies that the variable `var` is non-`null`.
*/
private ControlFlowNode nonNullBranchKill(LocalScopeVariable var, ControlFlowNode cfgnode) {
private ControlFlow::Node nonNullBranchKill(LocalScopeVariable var, ControlFlow::Node cfgnode) {
(cfgnode.getElement() = nonNullTest(var) and result = cfgnode.getATrueSuccessor())
or
(cfgnode.getElement() = failureIsNonNullTest(var) and result = cfgnode.getAFalseSuccessor())
}
/** Gets a node where the variable `var` may be `null`. */
ControlFlowNode maybeNullNode(LocalScopeVariable var) {
ControlFlow::Node maybeNullNode(LocalScopeVariable var) {
result = nullDef(var).getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
mid = maybeNullNode(var) and
not mid.getElement() = nonNullDef(var) and
mid.getASuccessor() = result and
@@ -441,10 +439,10 @@ ControlFlowNode maybeNullNode(LocalScopeVariable var) {
}
/** Gets a node where the variable `var` may be non-`null`. */
ControlFlowNode maybeNonNullNode(LocalScopeVariable var) {
ControlFlow::Node maybeNonNullNode(LocalScopeVariable var) {
result = nonNullDef(var).getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
mid = maybeNonNullNode(var) and
not mid.getElement() = nullDef(var) and
mid.getASuccessor() = result and

View File

@@ -5,8 +5,7 @@
import csharp
module Ssa {
class BasicBlock = ControlFlowGraph::BasicBlock;
class ControlFlowNode = ControlFlowGraph::ControlFlowNode;
class BasicBlock = ControlFlow::BasicBlock;
private module SourceVariableImpl {
private import AssignableDefinitions
@@ -207,7 +206,7 @@ module Ssa {
* Holds if the `i`th node `node` of basic block `bb` reads source variable `v`.
* The read at `node` is of kind `rk`.
*/
predicate variableRead(BasicBlock bb, int i, SourceVariable v, ControlFlowNode node, ReadKind rk) {
predicate variableRead(BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk) {
v.getAnAccess().(AssignableRead) = node.getElement() and
node = bb.getNode(i) and
rk = ActualRead()
@@ -222,7 +221,7 @@ module Ssa {
rk = RefReadBeforeWrite()
}
private predicate outRefExitRead(ControlFlowGraph::ExitBasicBlock ebb, int i, LocalScopeSourceVariable v, ControlFlowGraph::CallableExitNode node) {
private predicate outRefExitRead(ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::ExitNode node) {
exists(LocalScopeVariable lsv |
lsv = v.getAssignable() and
ebb.getNode(i) = node and
@@ -231,7 +230,7 @@ module Ssa {
)
}
private predicate capturedVarExitRead(ControlFlowGraph::ExitBasicBlock ebb, int i, LocalScopeSourceVariable v, ControlFlowGraph::CallableExitNode node) {
private predicate capturedVarExitRead(ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::ExitNode node) {
exists(BasicBlock bb |
variableDefinition(bb, _, v, _) |
ebb.getNode(i) = node and
@@ -240,7 +239,7 @@ module Ssa {
)
}
private predicate refReadBeforeWrite(BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlowNode node) {
private predicate refReadBeforeWrite(BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Node node) {
exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv |
def.getTarget() = lv and
lv.isRef() and
@@ -692,7 +691,7 @@ module Ssa {
* same basic block without crossing another SSA definition of `v`.
* The read at `node` is of kind `rk`.
*/
private predicate ssaDefReachesReadWithinBlock(TrackedVar v, TrackedDefinition def, ControlFlowNode read, ReadKind rk) {
private predicate ssaDefReachesReadWithinBlock(TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk) {
exists(BasicBlock bb, int rankix, int i |
ssaDefReachesRank(bb, def, rankix, v) and
rankix = ssaRefRank(bb, i, v, SsaRead()) and
@@ -873,7 +872,7 @@ module Ssa {
* The read at `node` is of kind `rk`.
*/
cached
predicate ssaDefReachesRead(TrackedVar v, TrackedDefinition def, ControlFlowNode read, ReadKind rk) {
predicate ssaDefReachesRead(TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk) {
ssaDefReachesReadWithinBlock(v, def, read, rk)
or
exists(BasicBlock bb |
@@ -1615,7 +1614,7 @@ module Ssa {
* `c` may read the value of the captured variable.
*/
private predicate capturerReads(Callable c, LocalScopeVariable v) {
exists(ControlFlowGraph::EntryBasicBlock ebb, LocalScopeSourceVariable lssv |
exists(ControlFlow::BasicBlocks::EntryBlock ebb, LocalScopeSourceVariable lssv |
liveAtEntry(ebb, lssv, _) |
v = lssv.getAssignable() and
c = ebb.getCallable() and
@@ -1873,7 +1872,7 @@ module Ssa {
)
}
or
TSsaImplicitEntryDef(TrackedVar v, ControlFlowGraph::EntryBasicBlock ebb) {
TSsaImplicitEntryDef(TrackedVar v, ControlFlow::BasicBlocks::EntryBlock ebb) {
liveAtEntry(ebb, v, _)
and
exists(Callable c |
@@ -1921,7 +1920,7 @@ module Ssa {
bb.getNode(i + 1) = v.getAnAccess().(AssignableRead).getAControlFlowNode()
}
or
TPhiNode(TrackedVar v, ControlFlowGraph::JoinBlock bb) {
TPhiNode(TrackedVar v, ControlFlow::BasicBlocks::JoinBlock bb) {
liveAtEntry(bb, v, _)
and
exists(BasicBlock bb1, Definition def |
@@ -2067,7 +2066,7 @@ module Ssa {
* - The reads of `this.Field` on lines 10 and 11 can be reached from the phi
* node between lines 9 and 10.
*/
AssignableRead getAReadAtNode(ControlFlowNode cfn) {
AssignableRead getAReadAtNode(ControlFlow::Node cfn) {
ssaDefReachesRead(_, this, cfn, _) and
result.getAControlFlowNode() = cfn
}
@@ -2250,7 +2249,7 @@ module Ssa {
* parameter may remain unchanged throughout the rest of the enclosing callable.
*/
predicate isLiveOutRefParameterDefinition(Parameter p) {
exists(Definition def, ControlFlowNode read, SourceVariable v |
exists(Definition def, ControlFlow::Node read, SourceVariable v |
this = def.getAnUltimateDefinition() |
ssaDefReachesRead(v, def, read, OutRefExitRead()) and
v.getAssignable() = p
@@ -2371,7 +2370,7 @@ module Ssa {
class ImplicitEntryDefinition extends ImplicitDefinition, TSsaImplicitEntryDef {
/** Gets the callable that this entry definition belongs to. */
Callable getCallable() {
exists(ControlFlowGraph::EntryBasicBlock ebb |
exists(ControlFlow::BasicBlocks::EntryBlock ebb |
this = TSsaImplicitEntryDef(_, ebb) and
result = ebb.getCallable()
)
@@ -2533,7 +2532,7 @@ module Ssa {
* does not exist in the source program.
*/
override Location getLocation() {
exists(ControlFlowGraph::JoinBlock bb |
exists(ControlFlow::BasicBlocks::JoinBlock bb |
this = TPhiNode(_, bb) and
result = bb.getFirstNode().getLocation()
)

View File

@@ -6,7 +6,7 @@ import csharp
* Provides a simple SSA implementation for local scope variables.
*/
module BaseSsa {
private import ControlFlowGraph
private import ControlFlow
private import AssignableDefinitions
private class SimpleLocalScopeVariable extends LocalScopeVariable {

View File

@@ -11,7 +11,7 @@ import Expr
* (`BinaryArithmeticOperation`).
*/
class ArithmeticOperation extends Operation, @arith_op_expr {
string getOperator() { none() }
override string getOperator() { none() }
}
/**

View File

@@ -38,10 +38,9 @@ class Call extends DotNet::Call, Expr, @call {
* Use `getARuntimeTarget()` instead to get a potential run-time target (will
* include `B.M` in the example above).
*/
Callable getTarget() { none() }
override Callable getTarget() { none() }
/** Gets the `i`th argument of this call. */
Expr getArgument(int i) {
override Expr getArgument(int i) {
result = this.getChild(i) and i >= 0
}
@@ -49,8 +48,7 @@ class Call extends DotNet::Call, Expr, @call {
result = this.getArgument(i)
}
/** Gets an argument of this call. */
Expr getAnArgument() {
override Expr getAnArgument() {
result = getArgument(_)
}
@@ -189,7 +187,7 @@ class Call extends DotNet::Call, Expr, @call {
* - Line 16: There is no static target (delegate call) but the delegate `i => { }` (line
* 20) is a run-time target.
*/
Callable getARuntimeTarget() {
override Callable getARuntimeTarget() {
exists(DispatchCall dc | dc.getCall() = this | result = dc.getADynamicTarget())
}

View File

@@ -189,11 +189,11 @@ private module FormatFlow {
private class FormatConfiguration extends DataFlow::Configuration {
FormatConfiguration() { this = "format" }
predicate isSource(DataFlow::Node n) {
override predicate isSource(DataFlow::Node n) {
n.asExpr() instanceof StringLiteral
}
predicate isSink(DataFlow::Node n) {
override predicate isSink(DataFlow::Node n) {
exists(FormatCall c | n.asExpr() = c.getFormatExpr())
}
}

View File

@@ -77,7 +77,7 @@ class SystemWebHttpRequestClass extends SystemWebClass {
and
result.hasName("Url")
and
result.getType() = getSystemUriClass()
result.getType() instanceof SystemUriClass
}
}

View File

@@ -6,7 +6,7 @@ private import semmle.code.csharp.frameworks.system.Runtime
/** The `System.Runtime.InteropServices` namespace. */
class SystemRuntimeInteropServicesNamespace extends Namespace {
SystemRuntimeInteropServicesNamespace() {
this.getParentNamespace() = getSystemRuntimeNamespace() and
this.getParentNamespace() instanceof SystemRuntimeNamespace and
this.hasName("InteropServices")
}
}

View File

@@ -72,7 +72,7 @@ module MissingXMLValidation {
this.getExpr() = createCall.getArgumentForName("input")
}
string getReason() {
override string getReason() {
// No settings = no Schema validation
result = "there is no 'XmlReaderSettings' instance specifying schema validation." and not exists(createCall.getSettings()) or
/*

View File

@@ -50,7 +50,7 @@ module XMLEntityInjection {
).getAnArgument()
}
string getReason() {
override string getReason() {
exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(result) | this.getExpr() = r.getAnArgument())
}
}

View File

@@ -451,7 +451,7 @@ module XSS {
this.getExpr() = aspWrittenValue(inline)
}
string explanation() {
override string explanation() {
result = "member is [[\"accessed inline\"|\"" +makeUrl(inline.getLocation())+ "\"]] in an ASPX page"
}
}

View File

@@ -245,6 +245,14 @@
| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:22:106:30 | return ...; | 2 |
| Switch.cs:108:17:108:17 | 1 | Switch.cs:108:9:108:18 | return ...; | 3 |
| Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | exit Throw | 4 |
| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:18:117:18 | 3 | 7 |
| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | exit M10 | 1 |
| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:32 | ... == ... | 3 |
| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; | 2 |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | 2 |
| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:31 | ... == ... | 3 |
| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; | 2 |
| Switch.cs:120:17:120:17 | 1 | Switch.cs:120:9:120:18 | return ...; | 3 |
| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | ... is ... | 16 |
| TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | 1 |
| TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | exit M | 5 |

View File

@@ -470,6 +470,21 @@
| post | Switch.cs:106:29:106:29 | 1 | Switch.cs:106:29:106:29 | 1 |
| post | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 |
| post | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | enter Throw |
| post | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | enter M10 |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | enter M10 |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | exit M10 |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:25:117:25 | access to parameter s |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:43:117:43 | 1 |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:13:118:33 | case ...: |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:25:118:25 | access to parameter s |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:42:118:42 | 2 |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:120:17:120:17 | 1 |
| post | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s |
| post | Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 |
| post | Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:13:118:33 | case ...: |
| post | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s |
| post | Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 |
| post | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 |
| post | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | enter M |
| post | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; |
| post | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | enter M |
@@ -1709,6 +1724,26 @@
| pre | Switch.cs:106:29:106:29 | 1 | Switch.cs:106:29:106:29 | 1 |
| pre | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 |
| pre | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | enter Throw |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | enter M10 |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | exit M10 |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:25:117:25 | access to parameter s |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:43:117:43 | 1 |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:13:118:33 | case ...: |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:25:118:25 | access to parameter s |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:42:118:42 | 2 |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:120:17:120:17 | 1 |
| pre | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | exit M10 |
| pre | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s |
| pre | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:43:117:43 | 1 |
| pre | Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 |
| pre | Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:13:118:33 | case ...: |
| pre | Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:25:118:25 | access to parameter s |
| pre | Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:42:118:42 | 2 |
| pre | Switch.cs:118:13:118:33 | case ...: | Switch.cs:120:17:120:17 | 1 |
| pre | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s |
| pre | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:42:118:42 | 2 |
| pre | Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 |
| pre | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 |
| pre | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | enter M |
| pre | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:25:7:25 | ; |
| pre | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:8:9:8:28 | ... ...; |

View File

@@ -89,6 +89,8 @@
| Switch.cs:50:30:50:38 | ... != ... | Switch.cs:51:17:51:22 | break; | true |
| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:85:17:85:22 | break; | true |
| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:86:22:86:25 | true | false |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 | true |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 | true |
| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:25:7:25 | ; | true |
| VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:24:25:24 | access to local variable x | true |
| VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:28:25:28 | access to local variable y | false |

View File

@@ -1,6 +1,5 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
from ConditionBlock cb, BasicBlock controlled, boolean testIsTrue
from ControlFlow::BasicBlocks::ConditionBlock cb, ControlFlow::BasicBlock controlled, boolean testIsTrue
where cb.controls(controlled, testIsTrue)
select cb.getLastNode(), controlled.getFirstNode(), testIsTrue

View File

@@ -117,6 +117,10 @@
| 108 | 13 | cflow.cs:108:13:108:21 | ... != ... | false | 116 | 9 | cflow.cs:116:9:116:29 | ...; |
| 108 | 13 | cflow.cs:108:13:108:21 | ... != ... | true | 109 | 9 | cflow.cs:109:9:115:9 | {...} |
| 110 | 20 | cflow.cs:110:20:110:23 | true | true | 111 | 13 | cflow.cs:111:13:113:13 | {...} |
| 117 | 25 | Switch.cs:117:25:117:32 | ... == ... | false | 118 | 13 | Switch.cs:118:13:118:33 | case ...: |
| 117 | 25 | Switch.cs:117:25:117:32 | ... == ... | true | 117 | 43 | Switch.cs:117:43:117:43 | 1 |
| 118 | 25 | Switch.cs:118:25:118:31 | ... == ... | false | 120 | 17 | Switch.cs:120:17:120:17 | 1 |
| 118 | 25 | Switch.cs:118:25:118:31 | ... == ... | true | 118 | 42 | Switch.cs:118:42:118:42 | 2 |
| 127 | 32 | cflow.cs:127:32:127:44 | ... == ... | false | 127 | 53 | cflow.cs:127:53:127:57 | this access |
| 127 | 32 | cflow.cs:127:32:127:44 | ... == ... | true | 127 | 48 | cflow.cs:127:48:127:49 | "" |
| 162 | 48 | cflow.cs:162:48:162:51 | [exception: Exception] true | true | 163 | 9 | cflow.cs:163:9:165:9 | {...} |

View File

@@ -1,12 +1,11 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
ControlFlowNode successor(ControlFlowNode node, boolean kind) {
ControlFlow::Node successor(ControlFlow::Node node, boolean kind) {
(kind = true and result = node.getATrueSuccessor()) or
(kind = false and result = node.getAFalseSuccessor())
}
from ControlFlowNode node, ControlFlowNode successor, Location nl, Location sl, boolean kind
from ControlFlow::Node node, ControlFlow::Node successor, Location nl, Location sl, boolean kind
where successor = successor(node, kind)
and nl = node.getLocation()
and sl = successor.getLocation()

View File

@@ -819,6 +819,24 @@
| post | Switch.cs:111:17:111:21 | exit Throw | Switch.cs:111:28:111:48 | throw ... |
| post | Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:34:111:48 | object creation of type Exception |
| post | Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:17:111:21 | enter Throw |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:36:117:44 | return ...; |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:35:118:43 | return ...; |
| post | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:120:9:120:18 | return ...; |
| post | Switch.cs:114:5:121:5 | {...} | Switch.cs:113:9:113:11 | enter M10 |
| post | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:114:5:121:5 | {...} |
| post | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:9:119:9 | switch (...) {...} |
| post | Switch.cs:115:17:115:24 | access to property Length | Switch.cs:115:17:115:17 | access to parameter s |
| post | Switch.cs:117:13:117:34 | case ...: | Switch.cs:115:17:115:24 | access to property Length |
| post | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:13:117:34 | case ...: |
| post | Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:28:117:32 | "foo" |
| post | Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:25 | access to parameter s |
| post | Switch.cs:117:36:117:44 | return ...; | Switch.cs:117:43:117:43 | 1 |
| post | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:13:118:33 | case ...: |
| post | Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:28:118:31 | "fu" |
| post | Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:25 | access to parameter s |
| post | Switch.cs:118:35:118:43 | return ...; | Switch.cs:118:42:118:42 | 2 |
| post | Switch.cs:120:9:120:18 | return ...; | Switch.cs:120:16:120:17 | -... |
| post | Switch.cs:120:16:120:17 | -... | Switch.cs:120:17:120:17 | 1 |
| post | TypeAccesses.cs:3:10:3:10 | exit M | TypeAccesses.cs:8:13:8:27 | Type t = ... |
| post | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:3:10:3:10 | enter M |
| post | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:4:5:9:5 | {...} |
@@ -2643,6 +2661,27 @@
| pre | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:34:111:48 | object creation of type Exception |
| pre | Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:17:111:21 | exit Throw |
| pre | Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:28:111:48 | throw ... |
| pre | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:114:5:121:5 | {...} |
| pre | Switch.cs:114:5:121:5 | {...} | Switch.cs:115:9:119:9 | switch (...) {...} |
| pre | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:17:115:17 | access to parameter s |
| pre | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:24 | access to property Length |
| pre | Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:34 | case ...: |
| pre | Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 |
| pre | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:25:117:25 | access to parameter s |
| pre | Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:33 | case ...: |
| pre | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:28:117:32 | "foo" |
| pre | Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 |
| pre | Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:32 | ... == ... |
| pre | Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; |
| pre | Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 |
| pre | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:25:118:25 | access to parameter s |
| pre | Switch.cs:118:18:118:18 | 2 | Switch.cs:120:17:120:17 | 1 |
| pre | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:28:118:31 | "fu" |
| pre | Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 |
| pre | Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:31 | ... == ... |
| pre | Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; |
| pre | Switch.cs:120:16:120:17 | -... | Switch.cs:120:9:120:18 | return ...; |
| pre | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:16:120:17 | -... |
| pre | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:4:5:9:5 | {...} |
| pre | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:5:9:5:26 | ... ...; |
| pre | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:13:5:13 | access to local variable s |

View File

@@ -1,7 +1,6 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
from ControlFlowNode dom, ControlFlowNode node, string s
from ControlFlow::Node dom, ControlFlow::Node node, string s
where
dom.strictlyDominates(node) and dom.getASuccessor() = node and s = "pre"
or

View File

@@ -688,6 +688,28 @@
| Switch.cs:108:16:108:17 | -... | Switch.cs:108:9:108:18 | return ...; | semmle.label | successor |
| Switch.cs:108:17:108:17 | 1 | Switch.cs:108:16:108:17 | -... | semmle.label | successor |
| Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:28:111:48 | throw ... | semmle.label | successor |
| Switch.cs:114:5:121:5 | {...} | Switch.cs:115:9:119:9 | switch (...) {...} | semmle.label | successor |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:17:115:17 | access to parameter s | semmle.label | successor |
| Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:24 | access to property Length | semmle.label | successor |
| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:34 | case ...: | semmle.label | successor |
| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 | semmle.label | successor |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:25:117:25 | access to parameter s | semmle.label | match |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:33 | case ...: | semmle.label | no-match |
| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:28:117:32 | "foo" | semmle.label | successor |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 | semmle.label | true |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:118:13:118:33 | case ...: | semmle.label | false |
| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:32 | ... == ... | semmle.label | successor |
| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; | semmle.label | successor |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | semmle.label | successor |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:25:118:25 | access to parameter s | semmle.label | match |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:120:17:120:17 | 1 | semmle.label | no-match |
| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:28:118:31 | "fu" | semmle.label | successor |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 | semmle.label | true |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:120:17:120:17 | 1 | semmle.label | false |
| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:31 | ... == ... | semmle.label | successor |
| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; | semmle.label | successor |
| Switch.cs:120:16:120:17 | -... | Switch.cs:120:9:120:18 | return ...; | semmle.label | successor |
| Switch.cs:120:17:120:17 | 1 | Switch.cs:120:16:120:17 | -... | semmle.label | successor |
| TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:5:9:5:26 | ... ...; | semmle.label | successor |
| TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:13:5:13 | access to local variable s | semmle.label | successor |
| TypeAccesses.cs:5:13:5:13 | access to local variable s | TypeAccesses.cs:5:25:5:25 | access to parameter o | semmle.label | successor |

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowElement node, ControlFlowElement successor, string attr, string val) {
exists(ControlFlowEdgeType t |
exists(ControlFlow::SuccessorType t |
successor = node.getAControlFlowNode().getASuccessorByType(t).getElement() |
attr = "semmle.label" and
val = t.toString()

View File

@@ -722,6 +722,27 @@
| Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 |
| Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:34:111:48 | object creation of type Exception |
| Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:34:111:48 | object creation of type Exception |
| Switch.cs:114:5:121:5 | {...} | Switch.cs:114:5:121:5 | {...} |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:9:119:9 | switch (...) {...} |
| Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:17 | access to parameter s |
| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:115:17:115:17 | access to parameter s |
| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:13:117:34 | case ...: |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:18:117:18 | 3 |
| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:25:117:25 | access to parameter s |
| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:28:117:32 | "foo" |
| Switch.cs:117:36:117:44 | return ...; | Switch.cs:117:43:117:43 | 1 |
| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:13:118:33 | case ...: |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:18:118:18 | 2 |
| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:25:118:25 | access to parameter s |
| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:28:118:31 | "fu" |
| Switch.cs:118:35:118:43 | return ...; | Switch.cs:118:42:118:42 | 2 |
| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 |
| Switch.cs:120:9:120:18 | return ...; | Switch.cs:120:17:120:17 | 1 |
| Switch.cs:120:16:120:17 | -... | Switch.cs:120:17:120:17 | 1 |
| Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 |
| TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:4:5:9:5 | {...} |
| TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:9:5:26 | ... ...; |
| TypeAccesses.cs:5:13:5:13 | access to local variable s | TypeAccesses.cs:5:13:5:13 | access to local variable s |

View File

@@ -1,5 +1,5 @@
import csharp
import ControlFlowGraph::Internal
import ControlFlow::Internal
from ControlFlowElement cfe
select cfe, first(cfe)

View File

@@ -65,6 +65,7 @@
| Switch.cs:91:10:91:11 | M8 | Switch.cs:92:5:99:5 | {...} |
| Switch.cs:101:9:101:10 | M9 | Switch.cs:102:5:109:5 | {...} |
| Switch.cs:111:17:111:21 | Throw | Switch.cs:111:34:111:48 | object creation of type Exception |
| Switch.cs:113:9:113:11 | M10 | Switch.cs:114:5:121:5 | {...} |
| TypeAccesses.cs:3:10:3:10 | M | TypeAccesses.cs:4:5:9:5 | {...} |
| VarDecls.cs:5:18:5:19 | M1 | VarDecls.cs:6:5:11:5 | {...} |
| VarDecls.cs:13:12:13:13 | M2 | VarDecls.cs:14:5:17:5 | {...} |

View File

@@ -1020,6 +1020,40 @@
| Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 | normal |
| Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:28:111:48 | throw ... | throw(Exception) |
| Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:34:111:48 | object creation of type Exception | normal |
| Switch.cs:114:5:121:5 | {...} | Switch.cs:117:36:117:44 | return ...; | return |
| Switch.cs:114:5:121:5 | {...} | Switch.cs:118:35:118:43 | return ...; | return |
| Switch.cs:114:5:121:5 | {...} | Switch.cs:120:9:120:18 | return ...; | return |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:117:36:117:44 | return ...; | return |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:18:118:18 | 2 | no-match |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:25:118:31 | ... == ... | false/false |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:35:118:43 | return ...; | return |
| Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:17 | access to parameter s | normal |
| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:115:17:115:24 | access to property Length | normal |
| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 | no-match |
| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:25:117:32 | ... == ... | false/false |
| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:36:117:44 | return ...; | return |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:18:117:18 | 3 | match |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:18:117:18 | 3 | no-match |
| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s | normal |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:25:117:32 | ... == ... | false/false |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:25:117:32 | ... == ... | true/true |
| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:28:117:32 | "foo" | normal |
| Switch.cs:117:36:117:44 | return ...; | Switch.cs:117:36:117:44 | return ...; | return |
| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 | normal |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | no-match |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:25:118:31 | ... == ... | false/false |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:35:118:43 | return ...; | return |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:18:118:18 | 2 | match |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:18:118:18 | 2 | no-match |
| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s | normal |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:25:118:31 | ... == ... | false/false |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:25:118:31 | ... == ... | true/true |
| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:28:118:31 | "fu" | normal |
| Switch.cs:118:35:118:43 | return ...; | Switch.cs:118:35:118:43 | return ...; | return |
| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 | normal |
| Switch.cs:120:9:120:18 | return ...; | Switch.cs:120:9:120:18 | return ...; | return |
| Switch.cs:120:16:120:17 | -... | Switch.cs:120:16:120:17 | -... | normal |
| Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 | normal |
| TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:8:13:8:27 | Type t = ... | normal |
| TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:13:5:25 | String s = ... | normal |
| TypeAccesses.cs:5:13:5:13 | access to local variable s | TypeAccesses.cs:5:13:5:13 | access to local variable s | normal |

View File

@@ -1,5 +1,5 @@
import csharp
import ControlFlowGraph::Internal
import ControlFlow::Internal
private import semmle.code.csharp.controlflow.Completion
from ControlFlowElement cfe, Completion c

View File

@@ -1,12 +1,13 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
import ControlFlow
import Internal
import Nodes
class MyFinallySplitControlFlowNode extends ControlFlowElementNode {
class MyFinallySplitControlFlowNode extends ElementNode {
MyFinallySplitControlFlowNode() {
exists(FinallySplitting::FinallySplitType type |
type = this.getASplit().(FinallySplit).getType() |
not type instanceof ControlFlowEdgeSuccessor
not type instanceof SuccessorTypes::NormalSuccessor
)
}

View File

@@ -976,6 +976,32 @@
| Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:34:111:48 | object creation of type Exception | semmle.label | successor |
| Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:17:111:21 | exit Throw | semmle.label | exception(Exception) |
| Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:28:111:48 | throw ... | semmle.label | successor |
| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:114:5:121:5 | {...} | semmle.label | successor |
| Switch.cs:114:5:121:5 | {...} | Switch.cs:115:9:119:9 | switch (...) {...} | semmle.label | successor |
| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:17:115:17 | access to parameter s | semmle.label | successor |
| Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:24 | access to property Length | semmle.label | successor |
| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:34 | case ...: | semmle.label | successor |
| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 | semmle.label | successor |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:25:117:25 | access to parameter s | semmle.label | match |
| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:33 | case ...: | semmle.label | no-match |
| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:28:117:32 | "foo" | semmle.label | successor |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 | semmle.label | true |
| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:118:13:118:33 | case ...: | semmle.label | false |
| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:32 | ... == ... | semmle.label | successor |
| Switch.cs:117:36:117:44 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return |
| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; | semmle.label | successor |
| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | semmle.label | successor |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:25:118:25 | access to parameter s | semmle.label | match |
| Switch.cs:118:18:118:18 | 2 | Switch.cs:120:17:120:17 | 1 | semmle.label | no-match |
| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:28:118:31 | "fu" | semmle.label | successor |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 | semmle.label | true |
| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:120:17:120:17 | 1 | semmle.label | false |
| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:31 | ... == ... | semmle.label | successor |
| Switch.cs:118:35:118:43 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return |
| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; | semmle.label | successor |
| Switch.cs:120:9:120:18 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return |
| Switch.cs:120:16:120:17 | -... | Switch.cs:120:9:120:18 | return ...; | semmle.label | successor |
| Switch.cs:120:17:120:17 | 1 | Switch.cs:120:16:120:17 | -... | semmle.label | successor |
| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:4:5:9:5 | {...} | semmle.label | successor |
| TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:5:9:5:26 | ... ...; | semmle.label | successor |
| TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:13:5:13 | access to local variable s | semmle.label | successor |

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowNode node, ControlFlowNode successor, string attr, string val) {
exists(ControlFlowEdgeType t |
query predicate edges(ControlFlow::Node node, ControlFlow::Node successor, string attr, string val) {
exists(ControlFlow::SuccessorType t |
successor = node.getASuccessorByType(t) |
attr = "semmle.label" and
val = t.toString()

View File

@@ -109,4 +109,14 @@ class Switch
}
static bool Throw() => throw new Exception();
int M10(string s)
{
switch (s.Length)
{
case 3 when s=="foo" : return 1;
case 2 when s=="fu" : return 2;
}
return -1;
}
}

View File

@@ -250,6 +250,11 @@ class Patterns
{
case "xyz":
break;
case "" when 1 < 2:
break;
case "x" when o is string s4:
Console.WriteLine($"x {s4}");
break;
case int i2 when i2 > 0:
Console.WriteLine($"positive {i2}");
break;

View File

@@ -0,0 +1,3 @@
| CSharp7.cs:253:13:253:31 | case ...: | CSharp7.cs:253:26:253:30 | ... < ... |
| CSharp7.cs:255:13:255:41 | case ...: | CSharp7.cs:255:27:255:40 | ... is ... |
| CSharp7.cs:258:13:258:36 | case Int32 i2: | CSharp7.cs:258:30:258:35 | ... > ... |

View File

@@ -0,0 +1,4 @@
import csharp
from CaseStmt stmt
select stmt, stmt.getCondition()

View File

@@ -51,16 +51,18 @@
| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:242:18:242:18 | access to local variable o |
| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:245:18:245:18 | access to local variable o |
| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:249:17:249:17 | access to local variable o |
| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:255:27:255:27 | access to local variable o |
| CSharp7.cs:234:18:234:23 | Int32 i1 | CSharp7.cs:234:28:234:29 | access to local variable i1 |
| CSharp7.cs:234:18:234:23 | Int32 i1 | CSharp7.cs:236:38:236:39 | access to local variable i1 |
| CSharp7.cs:238:23:238:31 | String s1 | CSharp7.cs:240:41:240:42 | access to local variable s1 |
| CSharp7.cs:253:18:253:23 | Int32 i2 | CSharp7.cs:253:30:253:31 | access to local variable i2 |
| CSharp7.cs:253:18:253:23 | Int32 i2 | CSharp7.cs:254:47:254:48 | access to local variable i2 |
| CSharp7.cs:256:18:256:23 | Int32 i3 | CSharp7.cs:257:42:257:43 | access to local variable i3 |
| CSharp7.cs:259:18:259:26 | String s2 | CSharp7.cs:260:45:260:46 | access to local variable s2 |
| CSharp7.cs:278:13:278:48 | Dictionary<Int32,String> dict = ... | CSharp7.cs:279:20:279:23 | access to local variable dict |
| CSharp7.cs:279:13:279:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:281:39:281:42 | access to local variable list |
| CSharp7.cs:279:13:279:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:283:36:283:39 | access to local variable list |
| CSharp7.cs:279:13:279:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:285:32:285:35 | access to local variable list |
| CSharp7.cs:279:32:279:35 | item | CSharp7.cs:279:41:279:44 | access to parameter item |
| CSharp7.cs:279:32:279:35 | item | CSharp7.cs:279:51:279:54 | access to parameter item |
| CSharp7.cs:255:32:255:40 | String s4 | CSharp7.cs:256:40:256:41 | access to local variable s4 |
| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:258:30:258:31 | access to local variable i2 |
| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:259:47:259:48 | access to local variable i2 |
| CSharp7.cs:261:18:261:23 | Int32 i3 | CSharp7.cs:262:42:262:43 | access to local variable i3 |
| CSharp7.cs:264:18:264:26 | String s2 | CSharp7.cs:265:45:265:46 | access to local variable s2 |
| CSharp7.cs:283:13:283:48 | Dictionary<Int32,String> dict = ... | CSharp7.cs:284:20:284:23 | access to local variable dict |
| CSharp7.cs:284:13:284:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:286:39:286:42 | access to local variable list |
| CSharp7.cs:284:13:284:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:288:36:288:39 | access to local variable list |
| CSharp7.cs:284:13:284:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:290:32:290:35 | access to local variable list |
| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:41:284:44 | access to parameter item |
| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:51:284:54 | access to parameter item |

View File

@@ -15,4 +15,4 @@
| CSharp7.cs:165:13:165:31 | f2 | CSharp7.cs:165:25:165:30 | call to local function f |
| CSharp7.cs:177:9:177:40 | f | CSharp7.cs:177:31:177:39 | ... + ... |
| CSharp7.cs:178:9:178:32 | g | CSharp7.cs:178:31:178:31 | access to parameter s |
| CSharp7.cs:279:32:279:61 | (...) => ... | CSharp7.cs:279:40:279:61 | (..., ...) |
| CSharp7.cs:284:32:284:61 | (...) => ... | CSharp7.cs:284:40:284:61 | (..., ...) |

View File

@@ -1,6 +1,6 @@
| CSharp7.cs:281:9:281:47 | foreach (... ... in ...) ... | 0 | CSharp7.cs:281:23:281:23 | Int32 a | CSharp7.cs:281:23:281:23 | a | CSharp7.cs:281:39:281:42 | access to local variable list | CSharp7.cs:281:45:281:47 | {...} |
| CSharp7.cs:281:9:281:47 | foreach (... ... in ...) ... | 1 | CSharp7.cs:281:33:281:33 | String b | CSharp7.cs:281:33:281:33 | b | CSharp7.cs:281:39:281:42 | access to local variable list | CSharp7.cs:281:45:281:47 | {...} |
| CSharp7.cs:283:9:283:44 | foreach (... ... in ...) ... | 0 | CSharp7.cs:283:23:283:23 | Int32 a | CSharp7.cs:283:23:283:23 | a | CSharp7.cs:283:36:283:39 | access to local variable list | CSharp7.cs:283:42:283:44 | {...} |
| CSharp7.cs:283:9:283:44 | foreach (... ... in ...) ... | 1 | CSharp7.cs:283:30:283:30 | String b | CSharp7.cs:283:30:283:30 | b | CSharp7.cs:283:36:283:39 | access to local variable list | CSharp7.cs:283:42:283:44 | {...} |
| CSharp7.cs:285:9:285:40 | foreach (... ... in ...) ... | 0 | CSharp7.cs:285:23:285:23 | Int32 a | CSharp7.cs:285:23:285:23 | a | CSharp7.cs:285:32:285:35 | access to local variable list | CSharp7.cs:285:38:285:40 | {...} |
| CSharp7.cs:285:9:285:40 | foreach (... ... in ...) ... | 1 | CSharp7.cs:285:26:285:26 | String b | CSharp7.cs:285:26:285:26 | b | CSharp7.cs:285:32:285:35 | access to local variable list | CSharp7.cs:285:38:285:40 | {...} |
| CSharp7.cs:286:9:286:47 | foreach (... ... in ...) ... | 0 | CSharp7.cs:286:23:286:23 | Int32 a | CSharp7.cs:286:23:286:23 | a | CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:286:45:286:47 | {...} |
| CSharp7.cs:286:9:286:47 | foreach (... ... in ...) ... | 1 | CSharp7.cs:286:33:286:33 | String b | CSharp7.cs:286:33:286:33 | b | CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:286:45:286:47 | {...} |
| CSharp7.cs:288:9:288:44 | foreach (... ... in ...) ... | 0 | CSharp7.cs:288:23:288:23 | Int32 a | CSharp7.cs:288:23:288:23 | a | CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:288:42:288:44 | {...} |
| CSharp7.cs:288:9:288:44 | foreach (... ... in ...) ... | 1 | CSharp7.cs:288:30:288:30 | String b | CSharp7.cs:288:30:288:30 | b | CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:288:42:288:44 | {...} |
| CSharp7.cs:290:9:290:40 | foreach (... ... in ...) ... | 0 | CSharp7.cs:290:23:290:23 | Int32 a | CSharp7.cs:290:23:290:23 | a | CSharp7.cs:290:32:290:35 | access to local variable list | CSharp7.cs:290:38:290:40 | {...} |
| CSharp7.cs:290:9:290:40 | foreach (... ... in ...) ... | 1 | CSharp7.cs:290:26:290:26 | String b | CSharp7.cs:290:26:290:26 | b | CSharp7.cs:290:32:290:35 | access to local variable list | CSharp7.cs:290:38:290:40 | {...} |

View File

@@ -1,57 +1,77 @@
| CSharp7.cs:249:9:270:9 | switch (...) {...} | CSharp7.cs:249:17:249:17 | access to local variable o | semmle.label | successor |
| CSharp7.cs:249:9:275:9 | switch (...) {...} | CSharp7.cs:249:17:249:17 | access to local variable o | semmle.label | successor |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:251:13:251:23 | case ...: | semmle.label | successor |
| CSharp7.cs:251:13:251:23 | case ...: | CSharp7.cs:251:18:251:22 | "xyz" | semmle.label | successor |
| CSharp7.cs:251:18:251:22 | "xyz" | CSharp7.cs:252:17:252:22 | break; | semmle.label | match |
| CSharp7.cs:251:18:251:22 | "xyz" | CSharp7.cs:253:13:253:36 | case Int32 i2: | semmle.label | no-match |
| CSharp7.cs:251:18:251:22 | "xyz" | CSharp7.cs:253:13:253:31 | case ...: | semmle.label | no-match |
| CSharp7.cs:252:17:252:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:253:13:253:36 | case Int32 i2: | CSharp7.cs:253:18:253:20 | access to type Int32 | semmle.label | successor |
| CSharp7.cs:253:18:253:20 | access to type Int32 | CSharp7.cs:253:18:253:23 | Int32 i2 | semmle.label | match |
| CSharp7.cs:253:18:253:20 | access to type Int32 | CSharp7.cs:256:13:256:24 | case Int32 i3: | semmle.label | no-match |
| CSharp7.cs:253:18:253:23 | Int32 i2 | CSharp7.cs:253:30:253:31 | access to local variable i2 | semmle.label | successor |
| CSharp7.cs:253:30:253:31 | access to local variable i2 | CSharp7.cs:253:35:253:35 | 0 | semmle.label | successor |
| CSharp7.cs:253:30:253:35 | ... > ... | CSharp7.cs:254:17:254:52 | ...; | semmle.label | true |
| CSharp7.cs:253:30:253:35 | ... > ... | CSharp7.cs:256:13:256:24 | case Int32 i3: | semmle.label | false |
| CSharp7.cs:253:35:253:35 | 0 | CSharp7.cs:253:30:253:35 | ... > ... | semmle.label | successor |
| CSharp7.cs:254:17:254:51 | call to method WriteLine | CSharp7.cs:255:17:255:22 | break; | semmle.label | successor |
| CSharp7.cs:254:17:254:52 | ...; | CSharp7.cs:254:37:254:45 | "positive " | semmle.label | successor |
| CSharp7.cs:254:35:254:50 | $"..." | CSharp7.cs:254:17:254:51 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:254:37:254:45 | "positive " | CSharp7.cs:254:47:254:48 | access to local variable i2 | semmle.label | successor |
| CSharp7.cs:254:47:254:48 | access to local variable i2 | CSharp7.cs:254:35:254:50 | $"..." | semmle.label | successor |
| CSharp7.cs:255:17:255:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:256:13:256:24 | case Int32 i3: | CSharp7.cs:256:18:256:20 | access to type Int32 | semmle.label | successor |
| CSharp7.cs:256:18:256:20 | access to type Int32 | CSharp7.cs:256:18:256:23 | Int32 i3 | semmle.label | match |
| CSharp7.cs:256:18:256:20 | access to type Int32 | CSharp7.cs:259:13:259:27 | case String s2: | semmle.label | no-match |
| CSharp7.cs:256:18:256:23 | Int32 i3 | CSharp7.cs:257:17:257:47 | ...; | semmle.label | successor |
| CSharp7.cs:257:17:257:46 | call to method WriteLine | CSharp7.cs:258:17:258:22 | break; | semmle.label | successor |
| CSharp7.cs:257:17:257:47 | ...; | CSharp7.cs:257:37:257:40 | "int " | semmle.label | successor |
| CSharp7.cs:257:35:257:45 | $"..." | CSharp7.cs:257:17:257:46 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:257:37:257:40 | "int " | CSharp7.cs:257:42:257:43 | access to local variable i3 | semmle.label | successor |
| CSharp7.cs:257:42:257:43 | access to local variable i3 | CSharp7.cs:257:35:257:45 | $"..." | semmle.label | successor |
| CSharp7.cs:258:17:258:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:259:13:259:27 | case String s2: | CSharp7.cs:259:18:259:23 | access to type String | semmle.label | successor |
| CSharp7.cs:259:18:259:23 | access to type String | CSharp7.cs:259:18:259:26 | String s2 | semmle.label | match |
| CSharp7.cs:259:18:259:23 | access to type String | CSharp7.cs:262:13:262:26 | case Double: | semmle.label | no-match |
| CSharp7.cs:259:18:259:26 | String s2 | CSharp7.cs:260:17:260:50 | ...; | semmle.label | successor |
| CSharp7.cs:260:17:260:49 | call to method WriteLine | CSharp7.cs:261:17:261:22 | break; | semmle.label | successor |
| CSharp7.cs:260:17:260:50 | ...; | CSharp7.cs:260:37:260:43 | "string " | semmle.label | successor |
| CSharp7.cs:260:35:260:48 | $"..." | CSharp7.cs:260:17:260:49 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:260:37:260:43 | "string " | CSharp7.cs:260:45:260:46 | access to local variable s2 | semmle.label | successor |
| CSharp7.cs:260:45:260:46 | access to local variable s2 | CSharp7.cs:260:35:260:48 | $"..." | semmle.label | successor |
| CSharp7.cs:261:17:261:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:262:13:262:26 | case Double: | CSharp7.cs:262:18:262:23 | access to type Double | semmle.label | successor |
| CSharp7.cs:262:18:262:23 | access to type Double | CSharp7.cs:263:17:263:44 | ...; | semmle.label | match |
| CSharp7.cs:262:18:262:23 | access to type Double | CSharp7.cs:265:13:265:24 | case Object v2: | semmle.label | no-match |
| CSharp7.cs:263:17:263:43 | call to method WriteLine | CSharp7.cs:264:17:264:22 | break; | semmle.label | successor |
| CSharp7.cs:263:17:263:44 | ...; | CSharp7.cs:263:35:263:42 | "Double" | semmle.label | successor |
| CSharp7.cs:263:35:263:42 | "Double" | CSharp7.cs:263:17:263:43 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:264:17:264:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:265:13:265:24 | case Object v2: | CSharp7.cs:265:18:265:20 | access to type Object | semmle.label | successor |
| CSharp7.cs:265:18:265:20 | access to type Object | CSharp7.cs:265:18:265:23 | Object v2 | semmle.label | match |
| CSharp7.cs:265:18:265:20 | access to type Object | CSharp7.cs:267:13:267:20 | default: | semmle.label | no-match |
| CSharp7.cs:265:18:265:23 | Object v2 | CSharp7.cs:266:17:266:22 | break; | semmle.label | successor |
| CSharp7.cs:253:13:253:31 | case ...: | CSharp7.cs:253:18:253:19 | "" | semmle.label | successor |
| CSharp7.cs:253:18:253:19 | "" | CSharp7.cs:253:26:253:26 | 1 | semmle.label | match |
| CSharp7.cs:253:18:253:19 | "" | CSharp7.cs:255:13:255:41 | case ...: | semmle.label | no-match |
| CSharp7.cs:253:26:253:26 | 1 | CSharp7.cs:253:30:253:30 | 2 | semmle.label | successor |
| CSharp7.cs:253:26:253:30 | ... < ... | CSharp7.cs:254:17:254:22 | break; | semmle.label | true |
| CSharp7.cs:253:30:253:30 | 2 | CSharp7.cs:253:26:253:30 | ... < ... | semmle.label | successor |
| CSharp7.cs:254:17:254:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:255:13:255:41 | case ...: | CSharp7.cs:255:18:255:20 | "x" | semmle.label | successor |
| CSharp7.cs:255:18:255:20 | "x" | CSharp7.cs:255:27:255:27 | access to local variable o | semmle.label | match |
| CSharp7.cs:255:18:255:20 | "x" | CSharp7.cs:258:13:258:36 | case Int32 i2: | semmle.label | no-match |
| CSharp7.cs:255:27:255:27 | access to local variable o | CSharp7.cs:255:32:255:40 | String s4 | semmle.label | successor |
| CSharp7.cs:255:27:255:40 | ... is ... | CSharp7.cs:256:17:256:45 | ...; | semmle.label | true |
| CSharp7.cs:255:27:255:40 | ... is ... | CSharp7.cs:258:13:258:36 | case Int32 i2: | semmle.label | false |
| CSharp7.cs:255:32:255:40 | String s4 | CSharp7.cs:255:27:255:40 | ... is ... | semmle.label | successor |
| CSharp7.cs:256:17:256:44 | call to method WriteLine | CSharp7.cs:257:17:257:22 | break; | semmle.label | successor |
| CSharp7.cs:256:17:256:45 | ...; | CSharp7.cs:256:37:256:38 | "x " | semmle.label | successor |
| CSharp7.cs:256:35:256:43 | $"..." | CSharp7.cs:256:17:256:44 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:256:37:256:38 | "x " | CSharp7.cs:256:40:256:41 | access to local variable s4 | semmle.label | successor |
| CSharp7.cs:256:40:256:41 | access to local variable s4 | CSharp7.cs:256:35:256:43 | $"..." | semmle.label | successor |
| CSharp7.cs:257:17:257:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:258:13:258:36 | case Int32 i2: | CSharp7.cs:258:18:258:20 | access to type Int32 | semmle.label | successor |
| CSharp7.cs:258:18:258:20 | access to type Int32 | CSharp7.cs:258:18:258:23 | Int32 i2 | semmle.label | match |
| CSharp7.cs:258:18:258:20 | access to type Int32 | CSharp7.cs:261:13:261:24 | case Int32 i3: | semmle.label | no-match |
| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:258:30:258:31 | access to local variable i2 | semmle.label | successor |
| CSharp7.cs:258:30:258:31 | access to local variable i2 | CSharp7.cs:258:35:258:35 | 0 | semmle.label | successor |
| CSharp7.cs:258:30:258:35 | ... > ... | CSharp7.cs:259:17:259:52 | ...; | semmle.label | true |
| CSharp7.cs:258:30:258:35 | ... > ... | CSharp7.cs:261:13:261:24 | case Int32 i3: | semmle.label | false |
| CSharp7.cs:258:35:258:35 | 0 | CSharp7.cs:258:30:258:35 | ... > ... | semmle.label | successor |
| CSharp7.cs:259:17:259:51 | call to method WriteLine | CSharp7.cs:260:17:260:22 | break; | semmle.label | successor |
| CSharp7.cs:259:17:259:52 | ...; | CSharp7.cs:259:37:259:45 | "positive " | semmle.label | successor |
| CSharp7.cs:259:35:259:50 | $"..." | CSharp7.cs:259:17:259:51 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:259:37:259:45 | "positive " | CSharp7.cs:259:47:259:48 | access to local variable i2 | semmle.label | successor |
| CSharp7.cs:259:47:259:48 | access to local variable i2 | CSharp7.cs:259:35:259:50 | $"..." | semmle.label | successor |
| CSharp7.cs:260:17:260:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:261:13:261:24 | case Int32 i3: | CSharp7.cs:261:18:261:20 | access to type Int32 | semmle.label | successor |
| CSharp7.cs:261:18:261:20 | access to type Int32 | CSharp7.cs:261:18:261:23 | Int32 i3 | semmle.label | match |
| CSharp7.cs:261:18:261:20 | access to type Int32 | CSharp7.cs:264:13:264:27 | case String s2: | semmle.label | no-match |
| CSharp7.cs:261:18:261:23 | Int32 i3 | CSharp7.cs:262:17:262:47 | ...; | semmle.label | successor |
| CSharp7.cs:262:17:262:46 | call to method WriteLine | CSharp7.cs:263:17:263:22 | break; | semmle.label | successor |
| CSharp7.cs:262:17:262:47 | ...; | CSharp7.cs:262:37:262:40 | "int " | semmle.label | successor |
| CSharp7.cs:262:35:262:45 | $"..." | CSharp7.cs:262:17:262:46 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:262:37:262:40 | "int " | CSharp7.cs:262:42:262:43 | access to local variable i3 | semmle.label | successor |
| CSharp7.cs:262:42:262:43 | access to local variable i3 | CSharp7.cs:262:35:262:45 | $"..." | semmle.label | successor |
| CSharp7.cs:263:17:263:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:264:13:264:27 | case String s2: | CSharp7.cs:264:18:264:23 | access to type String | semmle.label | successor |
| CSharp7.cs:264:18:264:23 | access to type String | CSharp7.cs:264:18:264:26 | String s2 | semmle.label | match |
| CSharp7.cs:264:18:264:23 | access to type String | CSharp7.cs:267:13:267:26 | case Double: | semmle.label | no-match |
| CSharp7.cs:264:18:264:26 | String s2 | CSharp7.cs:265:17:265:50 | ...; | semmle.label | successor |
| CSharp7.cs:265:17:265:49 | call to method WriteLine | CSharp7.cs:266:17:266:22 | break; | semmle.label | successor |
| CSharp7.cs:265:17:265:50 | ...; | CSharp7.cs:265:37:265:43 | "string " | semmle.label | successor |
| CSharp7.cs:265:35:265:48 | $"..." | CSharp7.cs:265:17:265:49 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:265:37:265:43 | "string " | CSharp7.cs:265:45:265:46 | access to local variable s2 | semmle.label | successor |
| CSharp7.cs:265:45:265:46 | access to local variable s2 | CSharp7.cs:265:35:265:48 | $"..." | semmle.label | successor |
| CSharp7.cs:266:17:266:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:267:13:267:20 | default: | CSharp7.cs:268:17:268:52 | ...; | semmle.label | successor |
| CSharp7.cs:268:17:268:51 | call to method WriteLine | CSharp7.cs:269:17:269:22 | break; | semmle.label | successor |
| CSharp7.cs:268:17:268:52 | ...; | CSharp7.cs:268:35:268:50 | "Something else" | semmle.label | successor |
| CSharp7.cs:268:35:268:50 | "Something else" | CSharp7.cs:268:17:268:51 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:267:13:267:26 | case Double: | CSharp7.cs:267:18:267:23 | access to type Double | semmle.label | successor |
| CSharp7.cs:267:18:267:23 | access to type Double | CSharp7.cs:268:17:268:44 | ...; | semmle.label | match |
| CSharp7.cs:267:18:267:23 | access to type Double | CSharp7.cs:270:13:270:24 | case Object v2: | semmle.label | no-match |
| CSharp7.cs:268:17:268:43 | call to method WriteLine | CSharp7.cs:269:17:269:22 | break; | semmle.label | successor |
| CSharp7.cs:268:17:268:44 | ...; | CSharp7.cs:268:35:268:42 | "Double" | semmle.label | successor |
| CSharp7.cs:268:35:268:42 | "Double" | CSharp7.cs:268:17:268:43 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:269:17:269:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:270:13:270:24 | case Object v2: | CSharp7.cs:270:18:270:20 | access to type Object | semmle.label | successor |
| CSharp7.cs:270:18:270:20 | access to type Object | CSharp7.cs:270:18:270:23 | Object v2 | semmle.label | match |
| CSharp7.cs:270:18:270:20 | access to type Object | CSharp7.cs:272:13:272:20 | default: | semmle.label | no-match |
| CSharp7.cs:270:18:270:23 | Object v2 | CSharp7.cs:271:17:271:22 | break; | semmle.label | successor |
| CSharp7.cs:271:17:271:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |
| CSharp7.cs:272:13:272:20 | default: | CSharp7.cs:273:17:273:52 | ...; | semmle.label | successor |
| CSharp7.cs:273:17:273:51 | call to method WriteLine | CSharp7.cs:274:17:274:22 | break; | semmle.label | successor |
| CSharp7.cs:273:17:273:52 | ...; | CSharp7.cs:273:35:273:50 | "Something else" | semmle.label | successor |
| CSharp7.cs:273:35:273:50 | "Something else" | CSharp7.cs:273:17:273:51 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:274:17:274:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break |

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowNode n1, ControlFlowNode n2, string attr, string val) {
exists(SwitchStmt switch, ControlFlowEdgeType t |
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2, string attr, string val) {
exists(SwitchStmt switch, ControlFlow::SuccessorType t |
switch.getAControlFlowNode().getASuccessor*()=n1 |
n2 = n1.getASuccessorByType(t) and
attr = "semmle.label" and

View File

@@ -1,3 +1,4 @@
| CSharp7.cs:234:13:234:23 | ... is ... | CSharp7.cs:234:18:234:20 | access to type Int32 | Int32 | CSharp7.cs:234:18:234:23 | Int32 i1 | false |
| CSharp7.cs:238:18:238:31 | ... is ... | CSharp7.cs:238:23:238:28 | access to type String | String | CSharp7.cs:238:23:238:31 | String s1 | false |
| CSharp7.cs:245:18:245:28 | ... is ... | CSharp7.cs:245:23:245:25 | access to type Object | Object | CSharp7.cs:245:23:245:28 | Object v1 | true |
| CSharp7.cs:255:27:255:40 | ... is ... | CSharp7.cs:255:32:255:37 | access to type String | String | CSharp7.cs:255:32:255:40 | String s4 | false |

View File

@@ -154,35 +154,42 @@
| CSharp7.cs:242:18:242:18 | access to local variable o | CSharp7.cs:245:18:245:18 | access to local variable o |
| CSharp7.cs:242:18:242:18 | access to local variable o | CSharp7.cs:249:17:249:17 | access to local variable o |
| CSharp7.cs:245:18:245:18 | access to local variable o | CSharp7.cs:249:17:249:17 | access to local variable o |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:253:18:253:23 | SSA def(i2) |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:256:18:256:23 | SSA def(i3) |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:259:18:259:26 | SSA def(s2) |
| CSharp7.cs:253:18:253:23 | SSA def(i2) | CSharp7.cs:253:30:253:31 | access to local variable i2 |
| CSharp7.cs:253:30:253:31 | access to local variable i2 | CSharp7.cs:253:30:253:35 | ... > ... |
| CSharp7.cs:253:30:253:31 | access to local variable i2 | CSharp7.cs:254:47:254:48 | access to local variable i2 |
| CSharp7.cs:254:37:254:45 | "positive " | CSharp7.cs:254:35:254:50 | $"..." |
| CSharp7.cs:254:47:254:48 | access to local variable i2 | CSharp7.cs:254:35:254:50 | $"..." |
| CSharp7.cs:256:18:256:23 | SSA def(i3) | CSharp7.cs:257:42:257:43 | access to local variable i3 |
| CSharp7.cs:257:37:257:40 | "int " | CSharp7.cs:257:35:257:45 | $"..." |
| CSharp7.cs:257:42:257:43 | access to local variable i3 | CSharp7.cs:257:35:257:45 | $"..." |
| CSharp7.cs:259:18:259:26 | SSA def(s2) | CSharp7.cs:260:45:260:46 | access to local variable s2 |
| CSharp7.cs:260:37:260:43 | "string " | CSharp7.cs:260:35:260:48 | $"..." |
| CSharp7.cs:260:45:260:46 | access to local variable s2 | CSharp7.cs:260:35:260:48 | $"..." |
| CSharp7.cs:278:13:278:48 | SSA def(dict) | CSharp7.cs:279:20:279:23 | access to local variable dict |
| CSharp7.cs:278:20:278:48 | object creation of type Dictionary<Int32,String> | CSharp7.cs:278:13:278:48 | SSA def(dict) |
| CSharp7.cs:279:13:279:62 | SSA def(list) | CSharp7.cs:281:39:281:42 | access to local variable list |
| CSharp7.cs:279:20:279:62 | call to method Select | CSharp7.cs:279:13:279:62 | SSA def(list) |
| CSharp7.cs:279:32:279:35 | item | CSharp7.cs:279:41:279:44 | access to parameter item |
| CSharp7.cs:279:32:279:61 | [implicit call] (...) => ... | CSharp7.cs:279:20:279:62 | call to method Select |
| CSharp7.cs:279:41:279:44 | access to parameter item | CSharp7.cs:279:51:279:54 | access to parameter item |
| CSharp7.cs:279:41:279:48 | access to property Key | CSharp7.cs:279:40:279:61 | (..., ...) |
| CSharp7.cs:279:51:279:54 | access to parameter item | CSharp7.cs:279:51:279:60 | access to property Value |
| CSharp7.cs:279:51:279:60 | access to property Value | CSharp7.cs:279:40:279:61 | (..., ...) |
| CSharp7.cs:281:23:281:23 | Int32 a | CSharp7.cs:281:18:281:34 | (..., ...) |
| CSharp7.cs:281:33:281:33 | String b | CSharp7.cs:281:18:281:34 | (..., ...) |
| CSharp7.cs:281:39:281:42 | access to local variable list | CSharp7.cs:283:36:283:39 | access to local variable list |
| CSharp7.cs:283:23:283:23 | Int32 a | CSharp7.cs:283:18:283:31 | (..., ...) |
| CSharp7.cs:283:30:283:30 | String b | CSharp7.cs:283:18:283:31 | (..., ...) |
| CSharp7.cs:283:36:283:39 | access to local variable list | CSharp7.cs:285:32:285:35 | access to local variable list |
| CSharp7.cs:285:23:285:23 | Int32 a | CSharp7.cs:285:18:285:27 | (..., ...) |
| CSharp7.cs:285:26:285:26 | String b | CSharp7.cs:285:18:285:27 | (..., ...) |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:255:27:255:27 | access to local variable o |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:258:18:258:23 | SSA def(i2) |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:261:18:261:23 | SSA def(i3) |
| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:264:18:264:26 | SSA def(s2) |
| CSharp7.cs:253:26:253:26 | 1 | CSharp7.cs:253:26:253:30 | ... < ... |
| CSharp7.cs:253:30:253:30 | 2 | CSharp7.cs:253:26:253:30 | ... < ... |
| CSharp7.cs:255:27:255:27 | access to local variable o | CSharp7.cs:255:32:255:40 | SSA def(s4) |
| CSharp7.cs:255:32:255:40 | SSA def(s4) | CSharp7.cs:256:40:256:41 | access to local variable s4 |
| CSharp7.cs:256:37:256:38 | "x " | CSharp7.cs:256:35:256:43 | $"..." |
| CSharp7.cs:256:40:256:41 | access to local variable s4 | CSharp7.cs:256:35:256:43 | $"..." |
| CSharp7.cs:258:18:258:23 | SSA def(i2) | CSharp7.cs:258:30:258:31 | access to local variable i2 |
| CSharp7.cs:258:30:258:31 | access to local variable i2 | CSharp7.cs:258:30:258:35 | ... > ... |
| CSharp7.cs:258:30:258:31 | access to local variable i2 | CSharp7.cs:259:47:259:48 | access to local variable i2 |
| CSharp7.cs:259:37:259:45 | "positive " | CSharp7.cs:259:35:259:50 | $"..." |
| CSharp7.cs:259:47:259:48 | access to local variable i2 | CSharp7.cs:259:35:259:50 | $"..." |
| CSharp7.cs:261:18:261:23 | SSA def(i3) | CSharp7.cs:262:42:262:43 | access to local variable i3 |
| CSharp7.cs:262:37:262:40 | "int " | CSharp7.cs:262:35:262:45 | $"..." |
| CSharp7.cs:262:42:262:43 | access to local variable i3 | CSharp7.cs:262:35:262:45 | $"..." |
| CSharp7.cs:264:18:264:26 | SSA def(s2) | CSharp7.cs:265:45:265:46 | access to local variable s2 |
| CSharp7.cs:265:37:265:43 | "string " | CSharp7.cs:265:35:265:48 | $"..." |
| CSharp7.cs:265:45:265:46 | access to local variable s2 | CSharp7.cs:265:35:265:48 | $"..." |
| CSharp7.cs:283:13:283:48 | SSA def(dict) | CSharp7.cs:284:20:284:23 | access to local variable dict |
| CSharp7.cs:283:20:283:48 | object creation of type Dictionary<Int32,String> | CSharp7.cs:283:13:283:48 | SSA def(dict) |
| CSharp7.cs:284:13:284:62 | SSA def(list) | CSharp7.cs:286:39:286:42 | access to local variable list |
| CSharp7.cs:284:20:284:62 | call to method Select | CSharp7.cs:284:13:284:62 | SSA def(list) |
| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:41:284:44 | access to parameter item |
| CSharp7.cs:284:32:284:61 | [implicit call] (...) => ... | CSharp7.cs:284:20:284:62 | call to method Select |
| CSharp7.cs:284:41:284:44 | access to parameter item | CSharp7.cs:284:51:284:54 | access to parameter item |
| CSharp7.cs:284:41:284:48 | access to property Key | CSharp7.cs:284:40:284:61 | (..., ...) |
| CSharp7.cs:284:51:284:54 | access to parameter item | CSharp7.cs:284:51:284:60 | access to property Value |
| CSharp7.cs:284:51:284:60 | access to property Value | CSharp7.cs:284:40:284:61 | (..., ...) |
| CSharp7.cs:286:23:286:23 | Int32 a | CSharp7.cs:286:18:286:34 | (..., ...) |
| CSharp7.cs:286:33:286:33 | String b | CSharp7.cs:286:18:286:34 | (..., ...) |
| CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:288:36:288:39 | access to local variable list |
| CSharp7.cs:288:23:288:23 | Int32 a | CSharp7.cs:288:18:288:31 | (..., ...) |
| CSharp7.cs:288:30:288:30 | String b | CSharp7.cs:288:18:288:31 | (..., ...) |
| CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:290:32:290:35 | access to local variable list |
| CSharp7.cs:290:23:290:23 | Int32 a | CSharp7.cs:290:18:290:27 | (..., ...) |
| CSharp7.cs:290:26:290:26 | String b | CSharp7.cs:290:18:290:27 | (..., ...) |

View File

@@ -52,15 +52,16 @@
| CSharp7.cs:234:22:234:23 | i1 | int |
| CSharp7.cs:238:30:238:31 | s1 | string |
| CSharp7.cs:245:27:245:28 | v1 | object |
| CSharp7.cs:253:22:253:23 | i2 | int |
| CSharp7.cs:256:22:256:23 | i3 | int |
| CSharp7.cs:259:25:259:26 | s2 | string |
| CSharp7.cs:265:22:265:23 | v2 | object |
| CSharp7.cs:278:13:278:16 | dict | Dictionary<int, string> |
| CSharp7.cs:279:13:279:16 | list | IEnumerable<(int, string)> |
| CSharp7.cs:281:23:281:23 | a | int |
| CSharp7.cs:281:33:281:33 | b | string |
| CSharp7.cs:283:23:283:23 | a | int |
| CSharp7.cs:283:30:283:30 | b | string |
| CSharp7.cs:285:23:285:23 | a | int |
| CSharp7.cs:285:26:285:26 | b | string |
| CSharp7.cs:255:39:255:40 | s4 | string |
| CSharp7.cs:258:22:258:23 | i2 | int |
| CSharp7.cs:261:22:261:23 | i3 | int |
| CSharp7.cs:264:25:264:26 | s2 | string |
| CSharp7.cs:270:22:270:23 | v2 | object |
| CSharp7.cs:283:13:283:16 | dict | Dictionary<int, string> |
| CSharp7.cs:284:13:284:16 | list | IEnumerable<(int, string)> |
| CSharp7.cs:286:23:286:23 | a | int |
| CSharp7.cs:286:33:286:33 | b | string |
| CSharp7.cs:288:23:288:23 | a | int |
| CSharp7.cs:288:30:288:30 | b | string |
| CSharp7.cs:290:23:290:23 | a | int |
| CSharp7.cs:290:26:290:26 | b | string |

View File

@@ -32,6 +32,7 @@
| CSharp7.cs:177:38:177:39 | "" | CSharp7.cs:177:31:177:39 | ... + ... |
| CSharp7.cs:236:33:236:36 | "int " | CSharp7.cs:236:31:236:41 | $"..." |
| CSharp7.cs:240:33:240:39 | "string " | CSharp7.cs:240:31:240:44 | $"..." |
| CSharp7.cs:254:37:254:45 | "positive " | CSharp7.cs:254:35:254:50 | $"..." |
| CSharp7.cs:257:37:257:40 | "int " | CSharp7.cs:257:35:257:45 | $"..." |
| CSharp7.cs:260:37:260:43 | "string " | CSharp7.cs:260:35:260:48 | $"..." |
| CSharp7.cs:256:37:256:38 | "x " | CSharp7.cs:256:35:256:43 | $"..." |
| CSharp7.cs:259:37:259:45 | "positive " | CSharp7.cs:259:35:259:50 | $"..." |
| CSharp7.cs:262:37:262:40 | "int " | CSharp7.cs:262:35:262:45 | $"..." |
| CSharp7.cs:265:37:265:43 | "string " | CSharp7.cs:265:35:265:48 | $"..." |

View File

@@ -39,7 +39,7 @@
| CSharp7.cs:223:9:223:14 | (..., ...) | write |
| CSharp7.cs:224:9:224:18 | (..., ...) | write |
| CSharp7.cs:225:9:225:18 | (..., ...) | write |
| CSharp7.cs:279:40:279:61 | (..., ...) | read |
| CSharp7.cs:281:18:281:34 | (..., ...) | read |
| CSharp7.cs:283:18:283:31 | (..., ...) | read |
| CSharp7.cs:285:18:285:27 | (..., ...) | read |
| CSharp7.cs:284:40:284:61 | (..., ...) | read |
| CSharp7.cs:286:18:286:34 | (..., ...) | read |
| CSharp7.cs:288:18:288:31 | (..., ...) | read |
| CSharp7.cs:290:18:290:27 | (..., ...) | read |

View File

@@ -82,11 +82,11 @@
| CSharp7.cs:224:9:224:18 | (..., ...) | 1 | CSharp7.cs:224:17:224:17 | _ |
| CSharp7.cs:225:9:225:18 | (..., ...) | 0 | CSharp7.cs:225:10:225:10 | _ |
| CSharp7.cs:225:9:225:18 | (..., ...) | 1 | CSharp7.cs:225:17:225:17 | Double y |
| CSharp7.cs:279:40:279:61 | (..., ...) | 0 | CSharp7.cs:279:41:279:48 | access to property Key |
| CSharp7.cs:279:40:279:61 | (..., ...) | 1 | CSharp7.cs:279:51:279:60 | access to property Value |
| CSharp7.cs:281:18:281:34 | (..., ...) | 0 | CSharp7.cs:281:23:281:23 | Int32 a |
| CSharp7.cs:281:18:281:34 | (..., ...) | 1 | CSharp7.cs:281:33:281:33 | String b |
| CSharp7.cs:283:18:283:31 | (..., ...) | 0 | CSharp7.cs:283:23:283:23 | Int32 a |
| CSharp7.cs:283:18:283:31 | (..., ...) | 1 | CSharp7.cs:283:30:283:30 | String b |
| CSharp7.cs:285:18:285:27 | (..., ...) | 0 | CSharp7.cs:285:23:285:23 | Int32 a |
| CSharp7.cs:285:18:285:27 | (..., ...) | 1 | CSharp7.cs:285:26:285:26 | String b |
| CSharp7.cs:284:40:284:61 | (..., ...) | 0 | CSharp7.cs:284:41:284:48 | access to property Key |
| CSharp7.cs:284:40:284:61 | (..., ...) | 1 | CSharp7.cs:284:51:284:60 | access to property Value |
| CSharp7.cs:286:18:286:34 | (..., ...) | 0 | CSharp7.cs:286:23:286:23 | Int32 a |
| CSharp7.cs:286:18:286:34 | (..., ...) | 1 | CSharp7.cs:286:33:286:33 | String b |
| CSharp7.cs:288:18:288:31 | (..., ...) | 0 | CSharp7.cs:288:23:288:23 | Int32 a |
| CSharp7.cs:288:18:288:31 | (..., ...) | 1 | CSharp7.cs:288:30:288:30 | String b |
| CSharp7.cs:290:18:290:27 | (..., ...) | 0 | CSharp7.cs:290:23:290:23 | Int32 a |
| CSharp7.cs:290:18:290:27 | (..., ...) | 1 | CSharp7.cs:290:26:290:26 | String b |

View File

@@ -31,11 +31,11 @@
| (Int32,Int32,Int32) | (int, int, int) | ValueTuple<int, int, int> | 3 | 2 | CSharp7.cs:75:16:75:22 | Item3 |
| (Int32,Int32,Int32) | (int, int, int) | ValueTuple<int, int, int> | 3 | 2 | CSharp7.cs:75:34:75:34 | Item3 |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | CSharp7.cs:97:19:97:19 | Item1 |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | CSharp7.cs:279:41:279:48 | Key |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | CSharp7.cs:281:19:281:23 | a |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | CSharp7.cs:284:41:284:48 | Key |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | CSharp7.cs:286:19:286:23 | a |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | CSharp7.cs:97:22:97:37 | Item2 |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | CSharp7.cs:279:51:279:60 | Value |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | CSharp7.cs:281:26:281:33 | b |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | CSharp7.cs:284:51:284:60 | Value |
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | CSharp7.cs:286:26:286:33 | b |
| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple<string, (int, int)> | 2 | 0 | CSharp7.cs:109:10:109:15 | m1 |
| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple<string, (int, int)> | 2 | 0 | CSharp7.cs:109:29:109:37 | Item1 |
| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple<string, (int, int)> | 2 | 0 | CSharp7.cs:112:10:112:11 | m3 |

View File

@@ -1,7 +1,9 @@
| CSharp7.cs:251:13:251:23 | case ...: |
| CSharp7.cs:253:13:253:36 | case Int32 i2: |
| CSharp7.cs:256:13:256:24 | case Int32 i3: |
| CSharp7.cs:259:13:259:27 | case String s2: |
| CSharp7.cs:262:13:262:26 | case Double: |
| CSharp7.cs:265:13:265:24 | case Object v2: |
| CSharp7.cs:267:13:267:20 | default: |
| CSharp7.cs:253:13:253:31 | case ...: |
| CSharp7.cs:255:13:255:41 | case ...: |
| CSharp7.cs:258:13:258:36 | case Int32 i2: |
| CSharp7.cs:261:13:261:24 | case Int32 i3: |
| CSharp7.cs:264:13:264:27 | case String s2: |
| CSharp7.cs:267:13:267:26 | case Double: |
| CSharp7.cs:270:13:270:24 | case Object v2: |
| CSharp7.cs:272:13:272:20 | default: |

View File

@@ -1,4 +1,4 @@
| CSharp7.cs:253:13:253:36 | case Int32 i2: | CSharp7.cs:253:18:253:23 | Int32 i2 | CSharp7.cs:253:18:253:20 | access to type Int32 | Int32 | false |
| CSharp7.cs:256:13:256:24 | case Int32 i3: | CSharp7.cs:256:18:256:23 | Int32 i3 | CSharp7.cs:256:18:256:20 | access to type Int32 | Int32 | false |
| CSharp7.cs:259:13:259:27 | case String s2: | CSharp7.cs:259:18:259:26 | String s2 | CSharp7.cs:259:18:259:23 | access to type String | String | false |
| CSharp7.cs:265:13:265:24 | case Object v2: | CSharp7.cs:265:18:265:23 | Object v2 | CSharp7.cs:265:18:265:20 | access to type Object | Object | true |
| CSharp7.cs:258:13:258:36 | case Int32 i2: | CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:258:18:258:20 | access to type Int32 | Int32 | false |
| CSharp7.cs:261:13:261:24 | case Int32 i3: | CSharp7.cs:261:18:261:23 | Int32 i3 | CSharp7.cs:261:18:261:20 | access to type Int32 | Int32 | false |
| CSharp7.cs:264:13:264:27 | case String s2: | CSharp7.cs:264:18:264:26 | String s2 | CSharp7.cs:264:18:264:23 | access to type String | String | false |
| CSharp7.cs:270:13:270:24 | case Object v2: | CSharp7.cs:270:18:270:23 | Object v2 | CSharp7.cs:270:18:270:20 | access to type Object | Object | true |

View File

@@ -1 +1 @@
| CSharp7.cs:253:13:253:36 | case Int32 i2: | CSharp7.cs:253:30:253:35 | ... > ... |
| CSharp7.cs:258:13:258:36 | case Int32 i2: | CSharp7.cs:258:30:258:35 | ... > ... |

View File

@@ -1,11 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/** "Naive" def-use implementation. */
predicate defReaches(AssignableDefinition def, LocalScopeVariable v, ControlFlowNode cfn) {
predicate defReaches(AssignableDefinition def, LocalScopeVariable v, ControlFlow::Node cfn) {
def.getTarget() = v and cfn = def.getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
defReaches(def, v, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = v and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()

View File

@@ -1,11 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/** "Naive" parameter-use implementation. */
predicate parameterReaches(Parameter p, ControlFlowNode cfn) {
predicate parameterReaches(Parameter p, ControlFlow::Node cfn) {
cfn = p.getCallable().getEntryPoint().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
parameterReaches(p, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = p and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()

View File

@@ -1,11 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/** "Naive" use-use implementation. */
predicate useReaches(LocalScopeVariableRead read, LocalScopeVariable v, ControlFlowNode cfn) {
predicate useReaches(LocalScopeVariableRead read, LocalScopeVariable v, ControlFlow::Node cfn) {
read.getTarget() = v and cfn = read.getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
useReaches(read, v, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = v and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()
@@ -29,7 +28,7 @@ private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableRea
result = TLocalScopeVariableRead(read.getANextRead())
or
not exists(read.getANextRead()) and
exists(Ssa::Definition ssaDef, Ssa::PseudoDefinition pseudoDef, ControlFlowNode cfn, BasicBlock bb, int i |
exists(Ssa::Definition ssaDef, Ssa::PseudoDefinition pseudoDef, ControlFlow::Node cfn, ControlFlow::BasicBlock bb, int i |
ssaDef.getARead() = read |
pseudoDef.getAnInput() = ssaDef and
pseudoDef.definesAt(bb, i) and

View File

@@ -3,5 +3,5 @@ import csharp
from int uses, int live
where
uses = strictcount(Ssa::ExplicitDefinition ssa, AssignableRead read | read = ssa.getARead()) and
live = strictcount(Ssa::ExplicitDefinition ssa, ControlFlowGraph::BasicBlock bb | ssa.isLiveAtEndOfBlock(bb))
live = strictcount(Ssa::ExplicitDefinition ssa, ControlFlow::BasicBlock bb | ssa.isLiveAtEndOfBlock(bb))
select uses, live

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowNode node, ControlFlowNode successor, string attr, string val) {
exists(ControlFlowEdgeType t |
query predicate edges(ControlFlow::Node node, ControlFlow::Node successor, string attr, string val) {
exists(ControlFlow::SuccessorType t |
successor = node.getASuccessorByType(t) |
attr = "semmle.label" and
val = t.toString()

View File

@@ -43,3 +43,9 @@
| queries.cs:47:11:47:18 | call to method Select | 1 | queries.cs:47:18:47:18 | access to local variable a |
| queries.cs:51:11:51:18 | call to method Select | 0 | queries.cs:50:11:50:32 | String a = ... |
| queries.cs:51:11:51:18 | call to method Select | 1 | queries.cs:51:18:51:18 | access to local variable a |
| queries.cs:55:11:55:49 | call to method GroupJoin | 0 | queries.cs:54:11:54:25 | Int32 a = ... |
| queries.cs:55:11:55:49 | call to method GroupJoin | 1 | queries.cs:55:11:55:49 | IList<IList<Int32>> c = ... |
| queries.cs:55:11:55:49 | call to method GroupJoin | 2 | queries.cs:55:21:55:25 | access to local variable list2 |
| queries.cs:55:11:55:49 | call to method GroupJoin | 3 | queries.cs:55:30:55:30 | access to local variable a |
| queries.cs:55:11:55:49 | call to method GroupJoin | 4 | queries.cs:55:39:55:42 | access to indexer |
| queries.cs:55:11:55:49 | call to method GroupJoin | 5 | queries.cs:55:11:55:49 | IList<IList<Int32>> d = ... |

View File

@@ -49,6 +49,11 @@ class Queries
var list11 =
from string a in list7
select a;
var list12 =
from a in list1
join c in list2 on a equals c[0] into d
select (a,d);
}
class A : System.Collections.IEnumerable

View File

@@ -81,3 +81,28 @@ class Designations
return 0;
}
}
class WhileIs
{
void Test()
{
object x = null;
while(x is string s)
{
var y = s;
}
}
}
class ObjectInitializerType
{
struct Point
{
public object Name;
}
void F()
{
new Point() { Name = "Bob" };
}
}

View File

@@ -39,3 +39,10 @@
| Program.cs:69:5:69:8 | Boolean |
| Program.cs:69:16:69:18 | Int32 |
| Program.cs:75:5:75:7 | Int32 |
| Program.cs:87:5:87:8 | Void |
| Program.cs:89:9:89:14 | Object |
| Program.cs:90:20:90:25 | String |
| Program.cs:92:13:92:15 | String |
| Program.cs:101:16:101:21 | Object |
| Program.cs:104:5:104:8 | Void |
| Program.cs:106:13:106:17 | Point |

View File

@@ -0,0 +1 @@
| Program.cs:92:21:92:21 | access to local variable s |

View File

@@ -0,0 +1,5 @@
import csharp
from LocalVariable decl
where decl.getName() = "s"
select decl.getAnAccess()

View File

@@ -0,0 +1,14 @@
// semmle-extractor-options: --standalone
using System;
class Cfg
{
void F()
{
var v = new InvalidType();
Debug.Assert(v.a.b, "This is true");
new CounterCreationData() { CounterHelp = string.Empty, CounterType = v.Type };
}
}

View File

@@ -0,0 +1,18 @@
| ControlFlow.cs:7:10:7:10 | enter F | ControlFlow.cs:8:5:13:5 | {...} |
| ControlFlow.cs:8:5:13:5 | {...} | ControlFlow.cs:9:9:9:34 | ... ...; |
| ControlFlow.cs:9:9:9:34 | ... ...; | ControlFlow.cs:9:13:9:13 | access to local variable v |
| ControlFlow.cs:10:9:10:13 | Expression | ControlFlow.cs:10:22:10:22 | access to local variable v |
| ControlFlow.cs:10:9:10:43 | Call to unknown method | ControlFlow.cs:12:9:12:87 | ...; |
| ControlFlow.cs:10:9:10:44 | ...; | ControlFlow.cs:10:9:10:13 | Expression |
| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Expression |
| ControlFlow.cs:10:22:10:24 | Expression | ControlFlow.cs:10:22:10:26 | Expression |
| ControlFlow.cs:10:22:10:26 | Expression | ControlFlow.cs:10:29:10:42 | "This is true" |
| ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | Call to unknown method |
| ControlFlow.cs:12:35:12:86 | { ..., ... } | ControlFlow.cs:7:10:7:10 | exit F |
| ControlFlow.cs:12:37:12:47 | Expression | ControlFlow.cs:12:51:12:62 | access to field Empty |
| ControlFlow.cs:12:37:12:62 | ... = ... | ControlFlow.cs:12:65:12:75 | Expression |
| ControlFlow.cs:12:51:12:62 | access to field Empty | ControlFlow.cs:12:37:12:62 | ... = ... |
| ControlFlow.cs:12:65:12:75 | Expression | ControlFlow.cs:12:79:12:79 | access to local variable v |
| ControlFlow.cs:12:65:12:84 | ... = ... | ControlFlow.cs:12:35:12:86 | { ..., ... } |
| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Expression |
| ControlFlow.cs:12:79:12:84 | Expression | ControlFlow.cs:12:65:12:84 | ... = ... |

View File

@@ -0,0 +1,17 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/**
* A method call where the target is unknown.
* The purpose of this is to ensure that all MethodCall expressions
* have a valid `toString()`.
*/
class UnknownCall extends MethodCall {
UnknownCall() { not exists(this.getTarget()) }
override string toString() { result = "Call to unknown method" }
}
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2) {
n2 = n1.getASuccessor()
}

View File

@@ -397,7 +397,7 @@ class MockitoSettableField extends Field {
class MockitoMockMethod extends Method {
MockitoMockMethod() {
this.getDeclaringType().hasQualifiedName("org.mockito", "Mockito") and
this.hasName("mock")
(this.hasName("mock") or this.hasName("verify"))
}
}

View File

@@ -29,3 +29,4 @@
+ semmlecode-javascript-queries/Security/CWE-807/DifferentKindsComparisonBypass.ql: /Security/CWE/CWE-807
+ semmlecode-javascript-queries/Security/CWE-843/TypeConfusionThroughParameterTampering.ql: /Security/CWE/CWE-834
+ semmlecode-javascript-queries/Security/CWE-916/InsufficientPasswordHash.ql: /Security/CWE/CWE-916
+ semmlecode-javascript-queries/Security/CWE-918/RequestForgery.ql: /Security/CWE/CWE-918

View File

@@ -45,4 +45,5 @@ class OmittedArrayElement extends ArrayExpr {
}
from OmittedArrayElement ae
where not ae.getFile().getFileType().isTypeScript() // ignore quirks in TypeScript tokenizer
select ae, "Avoid omitted array elements."

View File

@@ -36,7 +36,8 @@ where s.hasSemicolonInserted() and
asi = strictcount(Stmt ss | asi(sc, ss, true)) and
nstmt = strictcount(Stmt ss | asi(sc, ss, _)) and
perc = ((1-asi/nstmt)*100).floor() and
perc >= 90
perc >= 90 and
not s.getFile().getFileType().isTypeScript() // ignore some quirks in the TypeScript tokenizer
select (LastLineOf)s, "Avoid automated semicolon insertion " +
"(" + perc + "% of all statements in $@ have an explicit semicolon).",
sc, "the enclosing " + sctype

View File

@@ -0,0 +1,79 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Directly incorporating user input into an HTTP request
without validating the input can facilitate different kinds of request
forgery attacks, where the attacker essentially controls the request.
If the vulnerable request is in server-side code, then security
mechanisms, such as external firewalls, can be bypassed.
If the vulnerable request is in client-side code, then unsuspecting
users can send malicious requests to other servers, potentially
resulting in a DDOS attack.
</p>
</overview>
<recommendation>
<p>
To guard against request forgery, it is advisable to avoid
putting user input directly into a remote request. If a flexible
remote request mechanism is required, it is recommended to maintain a
list of authorized request targets and choose from that list based on
the user input provided.
</p>
</recommendation>
<example>
<p>
The following example shows an HTTP request parameter
being used directly in a URL request without validating the input,
which facilitates an SSRF attack. The request
<code>http.get(...)</code> is vulnerable since attackers can choose
the value of <code>target</code> to be anything they want. For
instance, the attacker can choose
<code>"internal.example.com/#"</code> as the target, causing the URL
used in the request to be
<code>"https://internal.example.com/#.example.com/data"</code>.
</p>
<p>
A request to <code>https://internal.example.com</code> may
be problematic if that server is not meant to be
directly accessible from the attacker's machine.
</p>
<sample src="examples/RequestForgeryBad.js"/>
<p>
One way to remedy the problem is to use the user input to
select a known fixed string before performing the request:
</p>
<sample src="examples/RequestForgeryGood.js"/>
</example>
<references>
<li>OWASP: <a href="https://www.owasp.org/index.php/Server_Side_Request_Forgery">SSRF</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,18 @@
/**
* @name Uncontrolled data used in remote request
* @description Sending remote requests with user-controlled data allows for request forgery attacks.
* @kind problem
* @problem.severity error
* @precision medium
* @id js/request-forgery
* @tags security
* external/cwe/cwe-918
*/
import javascript
import semmle.javascript.security.dataflow.RequestForgery::RequestForgery
from Configuration cfg, DataFlow::Node source, Sink sink, DataFlow::Node request
where cfg.hasFlow(source, sink) and
request = sink.getARequest()
select request, "The $@ of this request depends on $@.", sink, sink.getKind(), source, "a user-provided value"

View File

@@ -0,0 +1,12 @@
import http from 'http';
import url from 'url';
var server = http.createServer(function(req, res) {
var target = url.parse(request.url, true).query.target;
// BAD: `target` is controlled by the attacker
http.get('https://' + target + ".example.com/data/", res => {
// process request response ...
});
});

View File

@@ -0,0 +1,19 @@
import http from 'http';
import url from 'url';
var server = http.createServer(function(req, res) {
var target = url.parse(request.url, true).query.target;
var subdomain;
if (target === 'EU') {
subdomain = "europe"
} else {
subdomain = "world"
}
// GOOD: `subdomain` is controlled by the server
http.get('https://' + subdomain + ".example.com/data/", res => {
// process request response ...
});
});

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