Merge branch 'main' into typeinfer

This commit is contained in:
Geoffrey White
2025-06-19 14:27:35 +01:00
68 changed files with 1676 additions and 1427 deletions

View File

@@ -216,6 +216,8 @@ private module OutputClobberingConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
/** Tracks flow of unsafe user input that is used to construct and evaluate an environment variable. */

View File

@@ -18,6 +18,8 @@ private module RequestForgeryConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgerySink }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
/** Tracks flow of unsafe user input that is used to construct and evaluate a system command. */

View File

@@ -17,6 +17,8 @@ private module SecretExfiltrationConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof SecretExfiltrationSink }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
/** Tracks flow of unsafe user input that is used in a context where it may lead to a secret exfiltration. */

View File

@@ -26,6 +26,8 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module MyFlow = TaintTracking::Global<MyConfig>;

View File

@@ -36,6 +36,8 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module MyFlow = TaintTracking::Global<MyConfig>;

View File

@@ -27,6 +27,8 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module MyFlow = TaintTracking::Global<MyConfig>;

View File

@@ -26,6 +26,8 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module MyFlow = TaintTracking::Global<MyConfig>;

View File

@@ -36,6 +36,8 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module MyFlow = TaintTracking::Global<MyConfig>;

View File

@@ -27,6 +27,8 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module MyFlow = TaintTracking::Global<MyConfig>;

View File

@@ -50,6 +50,8 @@ module WordexpTaintConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
module WordexpTaint = TaintTracking::Global<WordexpTaintConfig>;

View File

@@ -1,6 +1,22 @@
ql/go/ql/src/InconsistentCode/ConstantLengthComparison.ql
ql/go/ql/src/InconsistentCode/InconsistentLoopOrientation.ql
ql/go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql
ql/go/ql/src/InconsistentCode/MissingErrorCheck.ql
ql/go/ql/src/InconsistentCode/MistypedExponentiation.ql
ql/go/ql/src/InconsistentCode/UnhandledCloseWritableHandle.ql
ql/go/ql/src/InconsistentCode/WhitespaceContradictsPrecedence.ql
ql/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql
ql/go/ql/src/RedundantCode/CompareIdenticalValues.ql
ql/go/ql/src/RedundantCode/DeadStoreOfField.ql
ql/go/ql/src/RedundantCode/DeadStoreOfLocal.ql
ql/go/ql/src/RedundantCode/DuplicateBranches.ql
ql/go/ql/src/RedundantCode/DuplicateCondition.ql
ql/go/ql/src/RedundantCode/DuplicateSwitchCase.ql
ql/go/ql/src/RedundantCode/ExprHasNoEffect.ql
ql/go/ql/src/RedundantCode/ImpossibleInterfaceNilCheck.ql
ql/go/ql/src/RedundantCode/NegativeLengthCheck.ql
ql/go/ql/src/RedundantCode/RedundantExpr.ql
ql/go/ql/src/RedundantCode/RedundantRecover.ql
ql/go/ql/src/RedundantCode/SelfAssignment.ql
ql/go/ql/src/RedundantCode/ShiftOutOfRange.ql
ql/go/ql/src/RedundantCode/UnreachableStatement.ql

View File

@@ -1,6 +1,22 @@
ql/go/ql/src/InconsistentCode/ConstantLengthComparison.ql
ql/go/ql/src/InconsistentCode/InconsistentLoopOrientation.ql
ql/go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql
ql/go/ql/src/InconsistentCode/MissingErrorCheck.ql
ql/go/ql/src/InconsistentCode/MistypedExponentiation.ql
ql/go/ql/src/InconsistentCode/UnhandledCloseWritableHandle.ql
ql/go/ql/src/InconsistentCode/WhitespaceContradictsPrecedence.ql
ql/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql
ql/go/ql/src/RedundantCode/CompareIdenticalValues.ql
ql/go/ql/src/RedundantCode/DeadStoreOfField.ql
ql/go/ql/src/RedundantCode/DeadStoreOfLocal.ql
ql/go/ql/src/RedundantCode/DuplicateBranches.ql
ql/go/ql/src/RedundantCode/DuplicateCondition.ql
ql/go/ql/src/RedundantCode/DuplicateSwitchCase.ql
ql/go/ql/src/RedundantCode/ExprHasNoEffect.ql
ql/go/ql/src/RedundantCode/ImpossibleInterfaceNilCheck.ql
ql/go/ql/src/RedundantCode/NegativeLengthCheck.ql
ql/go/ql/src/RedundantCode/RedundantExpr.ql
ql/go/ql/src/RedundantCode/RedundantRecover.ql
ql/go/ql/src/RedundantCode/SelfAssignment.ql
ql/go/ql/src/RedundantCode/ShiftOutOfRange.ql
ql/go/ql/src/RedundantCode/UnreachableStatement.ql

View File

@@ -5,7 +5,10 @@
* @kind problem
* @problem.severity warning
* @id go/constant-length-comparison
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-129
* @precision high
*/

View File

@@ -8,7 +8,9 @@
* @kind problem
* @problem.severity error
* @id go/inconsistent-loop-direction
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-835
* @precision very-high
*/

View File

@@ -5,10 +5,9 @@
* @kind problem
* @problem.severity error
* @id go/index-out-of-bounds
* @tags reliability
* @tags quality
* reliability
* correctness
* logic
* quality
* external/cwe/cwe-193
* @precision high
*/

View File

@@ -5,10 +5,10 @@
* @kind problem
* @problem.severity warning
* @id go/missing-error-check
* @tags reliability
* correctness
* logic
* quality
* @tags quality
* reliability
* error-handling
* external/cwe/cwe-252
* @precision high
*/

View File

@@ -4,7 +4,10 @@
* @kind problem
* @problem.severity warning
* @id go/mistyped-exponentiation
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-480
* @precision high
*/

View File

@@ -7,11 +7,10 @@
* @problem.severity warning
* @precision high
* @id go/unhandled-writable-file-close
* @tags maintainability
* correctness
* call
* defer
* quality
* @tags quality
* reliability
* error-handling
* external/cwe/cwe-252
*/
import go

View File

@@ -1,11 +1,12 @@
/**
* @name Whitespace contradicts operator precedence
* @description Nested expressions where the formatting contradicts the grouping enforced by operator precedence
* are difficult to read and may even indicate a bug.
* are difficult to read and may indicate a bug.
* @kind problem
* @problem.severity warning
* @id go/whitespace-contradicts-precedence
* @tags maintainability
* @tags quality
* reliability
* correctness
* external/cwe/cwe-783
* @precision very-high

View File

@@ -4,10 +4,9 @@
* @kind problem
* @problem.severity warning
* @id go/unexpected-nil-value
* @tags reliability
* correctness
* logic
* quality
* @tags quality
* reliability
* error-handling
* @precision high
*/

View File

@@ -5,7 +5,9 @@
* @kind problem
* @problem.severity warning
* @id go/comparison-of-identical-expressions
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-570
* external/cwe/cwe-571
* @precision very-high

View File

@@ -4,7 +4,9 @@
* @kind problem
* @problem.severity warning
* @id go/useless-assignment-to-field
* @tags maintainability
* @tags quality
* maintainability
* useless-code
* external/cwe/cwe-563
* @precision very-high
*/

View File

@@ -5,7 +5,9 @@
* @kind problem
* @problem.severity warning
* @id go/useless-assignment-to-local
* @tags maintainability
* @tags quality
* maintainability
* useless-code
* external/cwe/cwe-563
* @precision very-high
*/

View File

@@ -6,7 +6,8 @@
* @problem.severity warning
* @precision very-high
* @id go/duplicate-branches
* @tags maintainability
* @tags quality
* reliability
* correctness
* external/cwe/cwe-561
*/

View File

@@ -5,7 +5,8 @@
* @kind problem
* @problem.severity error
* @id go/duplicate-condition
* @tags maintainability
* @tags quality
* reliability
* correctness
* external/cwe/cwe-561
* @precision very-high

View File

@@ -5,7 +5,8 @@
* @kind problem
* @problem.severity error
* @id go/duplicate-switch-case
* @tags maintainability
* @tags quality
* reliability
* correctness
* external/cwe/cwe-561
* @precision very-high

View File

@@ -5,7 +5,8 @@
* @kind problem
* @problem.severity warning
* @id go/useless-expression
* @tags maintainability
* @tags quality
* reliability
* correctness
* external/cwe/cwe-480
* external/cwe/cwe-561

View File

@@ -4,7 +4,10 @@
* @kind problem
* @problem.severity warning
* @id go/impossible-interface-nil-check
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-570
* @precision high
*/

View File

@@ -8,8 +8,10 @@
* @problem.severity warning
* @precision very-high
* @id go/negative-length-check
* @tags correctness
* quality
* @tags quality
* reliability
* correctness
* external/cwe/cwe-571
*/
import go

View File

@@ -6,7 +6,9 @@
* @kind problem
* @problem.severity warning
* @id go/redundant-operation
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-480
* external/cwe/cwe-561
* @precision very-high

View File

@@ -6,9 +6,10 @@
* @kind problem
* @problem.severity warning
* @id go/redundant-recover
* @tags maintainability
* @tags quality
* reliability
* correctness
* quality
* external/cwe/cwe-248
* @precision high
*/

View File

@@ -4,7 +4,9 @@
* @kind problem
* @problem.severity warning
* @id go/redundant-assignment
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-480
* external/cwe/cwe-561
* @precision high

View File

@@ -6,7 +6,9 @@
* @problem.severity warning
* @id go/shift-out-of-range
* @precision very-high
* @tags correctness
* @tags quality
* reliability
* correctness
* external/cwe/cwe-197
*/

View File

@@ -5,7 +5,8 @@
* @kind problem
* @problem.severity warning
* @id go/unreachable-statement
* @tags maintainability
* @tags quality
* reliability
* correctness
* external/cwe/cwe-561
* @precision very-high

View File

@@ -74,6 +74,8 @@ module Config implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof RegexpPattern }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) { none() }
}
module Flow = DataFlow::Global<Config>;

View File

@@ -101,6 +101,8 @@ module UntrustedToTemplateExecWithConversionConfig implements DataFlow::StateCon
conversion.getType().getUnderlyingType*() = unescapedType
)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module UntrustedToTemplateExecWithConversionFlow =

View File

@@ -27,6 +27,8 @@ module Config implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
/**

View File

@@ -0,0 +1,22 @@
---
category: queryMetadata
---
* The tag `quality` has been added to multiple Go quality queries for consistency. They have all been given a tag for one of the two top-level categories `reliability` or `maintainability`, and a tag for a sub-category. See [Query file metadata and alert message style guide](https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md#quality-query-sub-category-tags) for more information about these categories.
* The tag `external/cwe/cwe-129` has been added to `go/constant-length-comparison`.
* The tag `external/cwe/cwe-193` has been added to `go/index-out-of-bounds`.
* The tag `external/cwe/cwe-197` has been added to `go/shift-out-of-range`.
* The tag `external/cwe/cwe-248` has been added to `go/redundant-recover`.
* The tag `external/cwe/cwe-252` has been added to `go/missing-error-check` and `go/unhandled-writable-file-close`.
* The tag `external/cwe/cwe-480` has been added to `go/mistyped-exponentiation`.
* The tag `external/cwe/cwe-570` has been added to `go/impossible-interface-nil-check` and `go/comparison-of-identical-expressions`.
* The tag `external/cwe/cwe-571` has been added to `go/negative-length-check` and `go/comparison-of-identical-expressions`.
* The tag `external/cwe/cwe-783` has been added to `go/whitespace-contradicts-precedence`.
* The tag `external/cwe/cwe-835` has been added to `go/inconsistent-loop-direction`.
* The tag `error-handling` has been added to `go/missing-error-check`, `go/unhandled-writable-file-close`, and `go/unexpected-nil-value`.
* The tag `useless-code` has been added to `go/useless-assignment-to-field`, `go/useless-assignment-to-local`, `go/useless-expression`, and `go/unreachable-statement`.
* The tag `logic` has been removed from `go/index-out-of-bounds` and `go/unexpected-nil-value`.
* The tags `call` and `defer` have been removed from `go/unhandled-writable-file-close`.
* The tags `correctness` and `quality` have been reordered in `go/missing-error-check` and `go/unhandled-writable-file-close`.
* The tag `maintainability` has been changed to `reliability` for `go/unhandled-writable-file-close`.
* The tag order has been standardized to have `quality` first, followed by the top-level category (`reliability` or `maintainability`), then sub-category tags, and finally CWE tags.
* The description text has been updated in `go/whitespace-contradicts-precedence` to change "may even indicate" to "may indicate".

View File

@@ -44,6 +44,8 @@ module PamStartToAcctMgmtConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) { none() }
}
module PamStartToAcctMgmtFlow = TaintTracking::Global<PamStartToAcctMgmtConfig>;
@@ -59,6 +61,8 @@ module PamStartToAuthenticateConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) { none() }
}
module PamStartToAuthenticateFlow = TaintTracking::Global<PamStartToAuthenticateConfig>;

View File

@@ -47,6 +47,8 @@ module Config implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
/**

View File

@@ -23,6 +23,10 @@ module ApkInstallationConfig implements DataFlow::ConfigSig {
)
)
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
}
module ApkInstallationFlow = DataFlow::Global<ApkInstallationConfig>;

View File

@@ -49,6 +49,8 @@ module HardcodedCredentialApiCallConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node n) {
n.asExpr().(MethodCall).getMethod() instanceof MethodSystemGetenv
}
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -14,6 +14,8 @@ module HardcodedCredentialSourceCallConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof HardcodedExpr }
predicate isSink(DataFlow::Node n) { n.asExpr() instanceof FinalCredentialsSourceSink }
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -19,6 +19,8 @@ module HttpStringToUrlOpenMethodFlowConfig implements DataFlow::ConfigSig {
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -17,6 +17,8 @@ module BasicAuthFlowConfig implements DataFlow::ConfigSig {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(HttpUrlsAdditionalTaintStep c).step(node1, node2)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -19,6 +19,8 @@ private module NotificationTrackingConfig implements DataFlow::ConfigSig {
}
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() { any() }
}
/** Taint tracking flow for sensitive data flowing to system notifications. */
@@ -75,6 +77,8 @@ private module TextFieldTrackingConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() { any() }
}
/** A local flow step that also flows through access to fields containing `View`s */

View File

@@ -15,6 +15,8 @@ module FetchUntrustedResourceConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof UrlResourceSink }
predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof RequestForgerySanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Removed `encodeURI` and `escape` functions from the sanitizer list for request forgery.

View File

@@ -106,10 +106,12 @@ module RequestForgery {
private import Xss as Xss
/**
* A call to `encodeURI` or `encodeURIComponent`, viewed as a sanitizer for request forgery.
* A call to `encodeURIComponent`, viewed as a sanitizer for request forgery.
* These calls will escape "/" to "%2F", which is not a problem for request forgery.
* The result from calling `encodeURI` or `encodeURIComponent` is not a valid URL, and only makes sense
* The result from calling `encodeURIComponent` is not a valid URL, and only makes sense
* as a part of a URL.
*/
class UriEncodingSanitizer extends Sanitizer instanceof Xss::Shared::UriEncodingSanitizer { }
class UriEncodingSanitizer extends Sanitizer instanceof Xss::Shared::UriEncodingSanitizer {
UriEncodingSanitizer() { this.encodesPathSeparators() }
}
}

View File

@@ -47,15 +47,22 @@ module Shared {
}
/**
* A call to `encodeURI` or `encodeURIComponent`, viewed as a sanitizer for
* A call to `encodeURI`, `encodeURIComponent` or `escape`, viewed as a sanitizer for
* XSS vulnerabilities.
*/
class UriEncodingSanitizer extends Sanitizer, DataFlow::CallNode {
string name;
UriEncodingSanitizer() {
exists(string name | this = DataFlow::globalVarRef(name).getACall() |
name in ["encodeURI", "encodeURIComponent", "escape"]
)
this = DataFlow::globalVarRef(name).getACall() and
name in ["encodeURI", "encodeURIComponent", "escape"]
}
/**
* Holds if this URI encoding function properly encodes path separators,
* making it safe for request forgery prevention.
*/
predicate encodesPathSeparators() { name = "encodeURIComponent" }
}
/**

View File

@@ -33,6 +33,8 @@
| serverSide.js:141:3:141:30 | axios.g ... ring()) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:141:13:141:29 | target.toString() | The $@ of this request depends on a $@. | serverSide.js:141:13:141:29 | target.toString() | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
| serverSide.js:142:3:142:19 | axios.get(target) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:142:13:142:18 | target | The $@ of this request depends on a $@. | serverSide.js:142:13:142:18 | target | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
| serverSide.js:143:3:143:24 | axios.g ... t.href) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:143:13:143:23 | target.href | The $@ of this request depends on a $@. | serverSide.js:143:13:143:23 | target.href | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
| serverSide.js:145:3:145:23 | axios.g ... dedUrl) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:145:13:145:22 | encodedUrl | The $@ of this request depends on a $@. | serverSide.js:145:13:145:22 | encodedUrl | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
| serverSide.js:147:3:147:23 | axios.g ... pedUrl) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:147:13:147:22 | escapedUrl | The $@ of this request depends on a $@. | serverSide.js:147:13:147:22 | escapedUrl | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
edges
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | provenance | |
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | provenance | |
@@ -110,6 +112,8 @@ edges
| serverSide.js:130:9:130:45 | myUrl | serverSide.js:131:15:131:19 | myUrl | provenance | |
| serverSide.js:130:37:130:43 | tainted | serverSide.js:130:9:130:45 | myUrl | provenance | |
| serverSide.js:139:9:139:29 | input | serverSide.js:140:26:140:30 | input | provenance | |
| serverSide.js:139:9:139:29 | input | serverSide.js:144:32:144:36 | input | provenance | |
| serverSide.js:139:9:139:29 | input | serverSide.js:146:29:146:33 | input | provenance | |
| serverSide.js:139:17:139:29 | req.query.url | serverSide.js:139:9:139:29 | input | provenance | |
| serverSide.js:140:9:140:31 | target | serverSide.js:141:13:141:18 | target | provenance | |
| serverSide.js:140:9:140:31 | target | serverSide.js:142:13:142:18 | target | provenance | |
@@ -118,6 +122,12 @@ edges
| serverSide.js:140:26:140:30 | input | serverSide.js:140:18:140:31 | new URL(input) | provenance | Config |
| serverSide.js:141:13:141:18 | target | serverSide.js:141:13:141:29 | target.toString() | provenance | |
| serverSide.js:143:13:143:18 | target | serverSide.js:143:13:143:23 | target.href | provenance | |
| serverSide.js:144:9:144:37 | encodedUrl | serverSide.js:145:13:145:22 | encodedUrl | provenance | |
| serverSide.js:144:22:144:37 | encodeURI(input) | serverSide.js:144:9:144:37 | encodedUrl | provenance | |
| serverSide.js:144:32:144:36 | input | serverSide.js:144:22:144:37 | encodeURI(input) | provenance | |
| serverSide.js:146:9:146:34 | escapedUrl | serverSide.js:147:13:147:22 | escapedUrl | provenance | |
| serverSide.js:146:22:146:34 | escape(input) | serverSide.js:146:9:146:34 | escapedUrl | provenance | |
| serverSide.js:146:29:146:33 | input | serverSide.js:146:22:146:34 | escape(input) | provenance | |
nodes
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | semmle.label | { url } |
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | semmle.label | url |
@@ -221,4 +231,12 @@ nodes
| serverSide.js:142:13:142:18 | target | semmle.label | target |
| serverSide.js:143:13:143:18 | target | semmle.label | target |
| serverSide.js:143:13:143:23 | target.href | semmle.label | target.href |
| serverSide.js:144:9:144:37 | encodedUrl | semmle.label | encodedUrl |
| serverSide.js:144:22:144:37 | encodeURI(input) | semmle.label | encodeURI(input) |
| serverSide.js:144:32:144:36 | input | semmle.label | input |
| serverSide.js:145:13:145:22 | encodedUrl | semmle.label | encodedUrl |
| serverSide.js:146:9:146:34 | escapedUrl | semmle.label | escapedUrl |
| serverSide.js:146:22:146:34 | escape(input) | semmle.label | escape(input) |
| serverSide.js:146:29:146:33 | input | semmle.label | input |
| serverSide.js:147:13:147:22 | escapedUrl | semmle.label | escapedUrl |
subpaths

View File

@@ -141,4 +141,8 @@ var server2 = http.createServer(function(req, res) {
axios.get(target.toString()); // $Alert[js/request-forgery]
axios.get(target); // $Alert[js/request-forgery]
axios.get(target.href); // $Alert[js/request-forgery]
const encodedUrl = encodeURI(input);
axios.get(encodedUrl); // $Alert[js/request-forgery]
const escapedUrl = escape(input);
axios.get(escapedUrl); // $Alert[js/request-forgery]
});

View File

@@ -1,3 +1,4 @@
ql/python/ql/src/Classes/InitCallsSubclass/InitCallsSubclassMethod.ql
ql/python/ql/src/Functions/IterReturnsNonSelf.ql
ql/python/ql/src/Functions/NonCls.ql
ql/python/ql/src/Functions/NonSelf.ql

View File

@@ -0,0 +1 @@
| Test.qll:7:11:7:13 | ClasslessPredicate foo | This possibly local non-private inline predicate will not be inlined across the overlay frontier. This may negatively affect evaluation performance. Consider adding an `overlay[caller]` annotation to allow inlining across the overlay frontier. Note that adding an `overlay[caller]` annotation affects semantics under overlay evaluation. |

View File

@@ -0,0 +1 @@
queries/overlay/InlineOverlayCaller.ql

View File

@@ -0,0 +1,14 @@
overlay[local?]
module;
import ql
pragma[inline]
predicate foo(int x) { x = 42 }
overlay[caller]
pragma[inline]
predicate bar(int x) { x = 43 }
pragma[inline]
private predicate baz(int x) { x = 44 }

View File

@@ -88,6 +88,8 @@ private module HttpVerbConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
private module HttpVerbFlow = TaintTracking::Global<HttpVerbConfig>;

View File

@@ -48,6 +48,8 @@ private module WeakParamsConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node node) { node = any(PersistentWriteAccess a).getValue() }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
private module WeakParamsFlow = TaintTracking::Global<WeakParamsConfig>;

View File

@@ -21,6 +21,8 @@ private module BasicTaintConfig implements DataFlow::ConfigSig {
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
private module BasicTaintFlow = TaintTracking::Global<BasicTaintConfig>;

View File

@@ -182,8 +182,8 @@ final class CallCfgNode extends ExprCfgNode {
}
/** Gets the `i`th argument of this call, if any. */
ExprCfgNode getArgument(int i) {
any(ChildMapping mapping).hasCfgChild(node, node.getArgument(i), this, result)
ExprCfgNode getPositionalArgument(int i) {
any(ChildMapping mapping).hasCfgChild(node, node.getPositionalArgument(i), this, result)
}
}

View File

@@ -132,7 +132,7 @@ final class ParameterPosition extends TParameterPosition {
final class ArgumentPosition extends ParameterPosition {
/** Gets the argument of `call` at this position, if any. */
Expr getArgument(Call call) {
result = call.getArgument(this.getPosition())
result = call.getPositionalArgument(this.getPosition())
or
result = call.getReceiver() and this.isSelf()
}
@@ -145,7 +145,7 @@ final class ArgumentPosition extends ParameterPosition {
* as the synthetic `ReceiverNode` is the argument for the `self` parameter.
*/
predicate isArgumentForCall(ExprCfgNode arg, CallCfgNode call, ParameterPosition pos) {
call.getArgument(pos.getPosition()) = arg
call.getPositionalArgument(pos.getPosition()) = arg
or
call.getReceiver() = arg and pos.isSelf() and not call.getCall().receiverImplicitlyBorrowed()
}

View File

@@ -4,4 +4,6 @@
private import internal.CallImpl
final class ArgumentPosition = Impl::ArgumentPosition;
final class Call = Impl::Call;

View File

@@ -5,20 +5,37 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
private import codeql.rust.elements.Operation
module Impl {
newtype TArgumentPosition =
TPositionalArgumentPosition(int i) {
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
} or
TSelfArgumentPosition()
/** An argument position in a call. */
class ArgumentPosition extends TArgumentPosition {
/** Gets the index of the argument in the call, if this is a positional argument. */
int asPosition() { this = TPositionalArgumentPosition(result) }
/** Holds if this call position is a self argument. */
predicate isSelf() { this instanceof TSelfArgumentPosition }
/** Gets a string representation of this argument position. */
string toString() {
result = this.asPosition().toString()
or
this.isSelf() and result = "self"
}
}
/**
* An expression that calls a function.
*
* This class abstracts over the different ways in which a function can be called in Rust.
* This class abstracts over the different ways in which a function can be
* called in Rust.
*/
abstract class Call extends ExprImpl::Expr {
/** Gets the number of arguments _excluding_ any `self` argument. */
abstract int getNumberOfArguments();
/** Gets the receiver of this call if it is a method call. */
abstract Expr getReceiver();
/** Holds if the call has a receiver that might be implicitly borrowed. */
abstract predicate receiverImplicitlyBorrowed();
/** Holds if the receiver of this call is implicitly borrowed. */
predicate receiverImplicitlyBorrowed() { this.implicitBorrowAt(TSelfArgumentPosition()) }
/** Gets the trait targeted by this call, if any. */
abstract Trait getTrait();
@@ -26,8 +43,20 @@ module Impl {
/** Gets the name of the method called if this call is a method call. */
abstract string getMethodName();
/** Gets the argument at the given position, if any. */
abstract Expr getArgument(ArgumentPosition pos);
/** Holds if the argument at `pos` might be implicitly borrowed. */
abstract predicate implicitBorrowAt(ArgumentPosition pos);
/** Gets the number of arguments _excluding_ any `self` argument. */
int getNumberOfArguments() { result = count(this.getArgument(TPositionalArgumentPosition(_))) }
/** Gets the `i`th argument of this call, if any. */
abstract Expr getArgument(int i);
Expr getPositionalArgument(int i) { result = this.getArgument(TPositionalArgumentPosition(i)) }
/** Gets the receiver of this call if it is a method call. */
Expr getReceiver() { result = this.getArgument(TSelfArgumentPosition()) }
/** Gets the static target of this call, if any. */
Function getStaticTarget() {
@@ -54,15 +83,13 @@ module Impl {
override string getMethodName() { none() }
override Expr getReceiver() { none() }
override Trait getTrait() { none() }
override predicate receiverImplicitlyBorrowed() { none() }
override predicate implicitBorrowAt(ArgumentPosition pos) { none() }
override int getNumberOfArguments() { result = super.getArgList().getNumberOfArgs() }
override Expr getArgument(int i) { result = super.getArgList().getArg(i) }
override Expr getArgument(ArgumentPosition pos) {
result = super.getArgList().getArg(pos.asPosition())
}
}
private class CallExprMethodCall extends Call instanceof CallExpr {
@@ -73,8 +100,6 @@ module Impl {
override string getMethodName() { result = methodName }
override Expr getReceiver() { result = super.getArgList().getArg(0) }
override Trait getTrait() {
result = resolvePath(qualifier) and
// When the qualifier is `Self` and resolves to a trait, it's inside a
@@ -84,43 +109,50 @@ module Impl {
qualifier.toString() != "Self"
}
override predicate receiverImplicitlyBorrowed() { none() }
override predicate implicitBorrowAt(ArgumentPosition pos) { none() }
override int getNumberOfArguments() { result = super.getArgList().getNumberOfArgs() - 1 }
override Expr getArgument(int i) { result = super.getArgList().getArg(i + 1) }
override Expr getArgument(ArgumentPosition pos) {
pos.isSelf() and result = super.getArgList().getArg(0)
or
result = super.getArgList().getArg(pos.asPosition() + 1)
}
}
private class MethodCallExprCall extends Call instanceof MethodCallExpr {
override string getMethodName() { result = super.getIdentifier().getText() }
override Expr getReceiver() { result = this.(MethodCallExpr).getReceiver() }
override Trait getTrait() { none() }
override predicate receiverImplicitlyBorrowed() { any() }
override predicate implicitBorrowAt(ArgumentPosition pos) { pos.isSelf() }
override int getNumberOfArguments() { result = super.getArgList().getNumberOfArgs() }
override Expr getArgument(int i) { result = super.getArgList().getArg(i) }
override Expr getArgument(ArgumentPosition pos) {
pos.isSelf() and result = this.(MethodCallExpr).getReceiver()
or
result = super.getArgList().getArg(pos.asPosition())
}
}
private class OperatorCall extends Call instanceof Operation {
Trait trait;
string methodName;
int borrows;
OperatorCall() { super.isOverloaded(trait, methodName) }
OperatorCall() { super.isOverloaded(trait, methodName, borrows) }
override string getMethodName() { result = methodName }
override Expr getReceiver() { result = super.getOperand(0) }
override Trait getTrait() { result = trait }
override predicate receiverImplicitlyBorrowed() { none() }
override predicate implicitBorrowAt(ArgumentPosition pos) {
pos.isSelf() and borrows >= 1
or
pos.asPosition() = 0 and borrows = 2
}
override int getNumberOfArguments() { result = super.getNumberOfOperands() - 1 }
override Expr getArgument(int i) { result = super.getOperand(1) and i = 0 }
override Expr getArgument(ArgumentPosition pos) {
pos.isSelf() and result = super.getOperand(0)
or
pos.asPosition() = 0 and result = super.getOperand(1)
}
}
}

View File

@@ -9,79 +9,80 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
/**
* Holds if the operator `op` with arity `arity` is overloaded to a trait with
* the canonical path `path` and the method name `method`.
* the canonical path `path` and the method name `method`, and if it borrows its
* first `borrows` arguments.
*/
private predicate isOverloaded(string op, int arity, string path, string method) {
private predicate isOverloaded(string op, int arity, string path, string method, int borrows) {
arity = 1 and
(
// Negation
op = "-" and path = "core::ops::arith::Neg" and method = "neg"
op = "-" and path = "core::ops::arith::Neg" and method = "neg" and borrows = 0
or
// Not
op = "!" and path = "core::ops::bit::Not" and method = "not"
op = "!" and path = "core::ops::bit::Not" and method = "not" and borrows = 0
or
// Dereference
op = "*" and path = "core::ops::deref::Deref" and method = "deref"
op = "*" and path = "core::ops::deref::Deref" and method = "deref" and borrows = 0
)
or
arity = 2 and
(
// Comparison operators
op = "==" and path = "core::cmp::PartialEq" and method = "eq"
op = "==" and path = "core::cmp::PartialEq" and method = "eq" and borrows = 2
or
op = "!=" and path = "core::cmp::PartialEq" and method = "ne"
op = "!=" and path = "core::cmp::PartialEq" and method = "ne" and borrows = 2
or
op = "<" and path = "core::cmp::PartialOrd" and method = "lt"
op = "<" and path = "core::cmp::PartialOrd" and method = "lt" and borrows = 2
or
op = "<=" and path = "core::cmp::PartialOrd" and method = "le"
op = "<=" and path = "core::cmp::PartialOrd" and method = "le" and borrows = 2
or
op = ">" and path = "core::cmp::PartialOrd" and method = "gt"
op = ">" and path = "core::cmp::PartialOrd" and method = "gt" and borrows = 2
or
op = ">=" and path = "core::cmp::PartialOrd" and method = "ge"
op = ">=" and path = "core::cmp::PartialOrd" and method = "ge" and borrows = 2
or
// Arithmetic operators
op = "+" and path = "core::ops::arith::Add" and method = "add"
op = "+" and path = "core::ops::arith::Add" and method = "add" and borrows = 0
or
op = "-" and path = "core::ops::arith::Sub" and method = "sub"
op = "-" and path = "core::ops::arith::Sub" and method = "sub" and borrows = 0
or
op = "*" and path = "core::ops::arith::Mul" and method = "mul"
op = "*" and path = "core::ops::arith::Mul" and method = "mul" and borrows = 0
or
op = "/" and path = "core::ops::arith::Div" and method = "div"
op = "/" and path = "core::ops::arith::Div" and method = "div" and borrows = 0
or
op = "%" and path = "core::ops::arith::Rem" and method = "rem"
op = "%" and path = "core::ops::arith::Rem" and method = "rem" and borrows = 0
or
// Arithmetic assignment expressions
op = "+=" and path = "core::ops::arith::AddAssign" and method = "add_assign"
op = "+=" and path = "core::ops::arith::AddAssign" and method = "add_assign" and borrows = 1
or
op = "-=" and path = "core::ops::arith::SubAssign" and method = "sub_assign"
op = "-=" and path = "core::ops::arith::SubAssign" and method = "sub_assign" and borrows = 1
or
op = "*=" and path = "core::ops::arith::MulAssign" and method = "mul_assign"
op = "*=" and path = "core::ops::arith::MulAssign" and method = "mul_assign" and borrows = 1
or
op = "/=" and path = "core::ops::arith::DivAssign" and method = "div_assign"
op = "/=" and path = "core::ops::arith::DivAssign" and method = "div_assign" and borrows = 1
or
op = "%=" and path = "core::ops::arith::RemAssign" and method = "rem_assign"
op = "%=" and path = "core::ops::arith::RemAssign" and method = "rem_assign" and borrows = 1
or
// Bitwise operators
op = "&" and path = "core::ops::bit::BitAnd" and method = "bitand"
op = "&" and path = "core::ops::bit::BitAnd" and method = "bitand" and borrows = 0
or
op = "|" and path = "core::ops::bit::BitOr" and method = "bitor"
op = "|" and path = "core::ops::bit::BitOr" and method = "bitor" and borrows = 0
or
op = "^" and path = "core::ops::bit::BitXor" and method = "bitxor"
op = "^" and path = "core::ops::bit::BitXor" and method = "bitxor" and borrows = 0
or
op = "<<" and path = "core::ops::bit::Shl" and method = "shl"
op = "<<" and path = "core::ops::bit::Shl" and method = "shl" and borrows = 0
or
op = ">>" and path = "core::ops::bit::Shr" and method = "shr"
op = ">>" and path = "core::ops::bit::Shr" and method = "shr" and borrows = 0
or
// Bitwise assignment operators
op = "&=" and path = "core::ops::bit::BitAndAssign" and method = "bitand_assign"
op = "&=" and path = "core::ops::bit::BitAndAssign" and method = "bitand_assign" and borrows = 1
or
op = "|=" and path = "core::ops::bit::BitOrAssign" and method = "bitor_assign"
op = "|=" and path = "core::ops::bit::BitOrAssign" and method = "bitor_assign" and borrows = 1
or
op = "^=" and path = "core::ops::bit::BitXorAssign" and method = "bitxor_assign"
op = "^=" and path = "core::ops::bit::BitXorAssign" and method = "bitxor_assign" and borrows = 1
or
op = "<<=" and path = "core::ops::bit::ShlAssign" and method = "shl_assign"
op = "<<=" and path = "core::ops::bit::ShlAssign" and method = "shl_assign" and borrows = 1
or
op = ">>=" and path = "core::ops::bit::ShrAssign" and method = "shr_assign"
op = ">>=" and path = "core::ops::bit::ShrAssign" and method = "shr_assign" and borrows = 1
)
}
@@ -114,9 +115,9 @@ module Impl {
* Holds if this operation is overloaded to the method `methodName` of the
* trait `trait`.
*/
predicate isOverloaded(Trait trait, string methodName) {
predicate isOverloaded(Trait trait, string methodName, int borrows) {
isOverloaded(this.getOperatorName(), this.getNumberOfOperands(), trait.getCanonicalPath(),
methodName)
methodName, borrows)
}
}
}

View File

@@ -513,22 +513,20 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
private predicate paramPos(ParamList pl, Param p, int pos) { p = pl.getParam(pos) }
private newtype TDeclarationPosition =
TSelfDeclarationPosition() or
TPositionalDeclarationPosition(int pos) { paramPos(_, _, pos) } or
TArgumentDeclarationPosition(ArgumentPosition pos) or
TReturnDeclarationPosition()
class DeclarationPosition extends TDeclarationPosition {
predicate isSelf() { this = TSelfDeclarationPosition() }
predicate isSelf() { this.asArgumentPosition().isSelf() }
int asPosition() { this = TPositionalDeclarationPosition(result) }
int asPosition() { result = this.asArgumentPosition().asPosition() }
ArgumentPosition asArgumentPosition() { this = TArgumentDeclarationPosition(result) }
predicate isReturn() { this = TReturnDeclarationPosition() }
string toString() {
this.isSelf() and
result = "self"
or
result = this.asPosition().toString()
result = this.asArgumentPosition().toString()
or
this.isReturn() and
result = "(return)"
@@ -561,7 +559,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(int pos |
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
dpos = TPositionalDeclarationPosition(pos)
pos = dpos.asPosition()
)
}
@@ -582,9 +580,9 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
}
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(int p |
result = this.getTupleField(p).getTypeRepr().(TypeMention).resolveTypeAt(path) and
dpos = TPositionalDeclarationPosition(p)
exists(int pos |
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
pos = dpos.asPosition()
)
}
@@ -619,7 +617,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(Param p, int i |
paramPos(this.getParamList(), p, i) and
dpos = TPositionalDeclarationPosition(i) and
i = dpos.asPosition() and
result = inferAnnotatedType(p.getPat(), path)
)
or
@@ -652,22 +650,21 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
}
private newtype TAccessPosition =
TSelfAccessPosition(Boolean implicitlyBorrowed) or
TPositionalAccessPosition(int pos) { exists(TPositionalDeclarationPosition(pos)) } or
TArgumentAccessPosition(ArgumentPosition pos, Boolean borrowed) or
TReturnAccessPosition()
class AccessPosition extends TAccessPosition {
predicate isSelf(boolean implicitlyBorrowed) { this = TSelfAccessPosition(implicitlyBorrowed) }
ArgumentPosition getArgumentPosition() { this = TArgumentAccessPosition(result, _) }
int asPosition() { this = TPositionalAccessPosition(result) }
predicate isBorrowed() { this = TArgumentAccessPosition(_, true) }
predicate isReturn() { this = TReturnAccessPosition() }
string toString() {
this.isSelf(_) and
result = "self"
or
result = this.asPosition().toString()
exists(ArgumentPosition pos, boolean borrowed |
this = TArgumentAccessPosition(pos, borrowed) and
result = pos + ":" + borrowed
)
or
this.isReturn() and
result = "(return)"
@@ -687,10 +684,11 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
}
AstNode getNodeAt(AccessPosition apos) {
result = this.getArgument(apos.asPosition())
or
result = this.getReceiver() and
if this.receiverImplicitlyBorrowed() then apos.isSelf(true) else apos.isSelf(false)
exists(ArgumentPosition pos, boolean borrowed |
apos = TArgumentAccessPosition(pos, borrowed) and
result = this.getArgument(pos) and
if this.implicitBorrowAt(pos) then borrowed = true else borrowed = false
)
or
result = this and apos.isReturn()
}
@@ -707,9 +705,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
}
predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos) {
apos.isSelf(_) and dpos.isSelf()
or
apos.asPosition() = dpos.asPosition()
apos.getArgumentPosition() = dpos.asArgumentPosition()
or
apos.isReturn() and dpos.isReturn()
}
@@ -719,10 +715,13 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
predicate adjustAccessType(
AccessPosition apos, Declaration target, TypePath path, Type t, TypePath pathAdj, Type tAdj
) {
if apos.isSelf(true)
if apos.isBorrowed()
then
exists(Type selfParamType |
selfParamType = target.getParameterType(TSelfDeclarationPosition(), TypePath::nil())
selfParamType =
target
.getParameterType(TArgumentDeclarationPosition(apos.getArgumentPosition()),
TypePath::nil())
|
if selfParamType = TRefType()
then
@@ -778,13 +777,10 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) {
|
n = a.getNodeAt(apos) and
result = CallExprBaseMatching::inferAccessType(a, apos, path0) and
// temporary workaround until implicit borrows are handled correctly
if a instanceof Operation then apos.isReturn() else any()
|
if apos.isSelf(_)
if apos.isBorrowed()
then
exists(Type receiverType | receiverType = inferType(n) |
if receiverType = TRefType()
exists(Type argType | argType = inferType(n) |
if argType = TRefType()
then
path = path0 and
path0.isCons(TRefTypeParameter(), _)
@@ -795,7 +791,7 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) {
path = TypePath::cons(TRefTypeParameter(), path0)
else (
not (
receiverType.(StructType).asItemNode() instanceof StringStruct and
argType.(StructType).asItemNode() instanceof StringStruct and
result.(StructType).asItemNode() instanceof Builtins::Str
) and
(
@@ -1394,7 +1390,7 @@ private Function getMethodFromImpl(MethodCall mc) {
or
exists(int pos, TypePath path, Type type |
methodResolutionDependsOnArgument(impl, mc.getMethodName(), result, pos, path, type) and
inferType(mc.getArgument(pos), path) = type
inferType(mc.getPositionalArgument(pos), path) = type
)
)
}
@@ -1429,7 +1425,8 @@ private module Cached {
cached
predicate receiverHasImplicitDeref(AstNode receiver) {
exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos |
apos.isSelf(true) and
apos.getArgumentPosition().isSelf() and
apos.isBorrowed() and
receiver = a.getNodeAt(apos) and
inferType(receiver) = TRefType() and
CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) != TRefType()
@@ -1440,7 +1437,8 @@ private module Cached {
cached
predicate receiverHasImplicitBorrow(AstNode receiver) {
exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos |
apos.isSelf(true) and
apos.getArgumentPosition().isSelf() and
apos.isBorrowed() and
receiver = a.getNodeAt(apos) and
CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) = TRefType() and
inferType(receiver) != TRefType()
@@ -1632,7 +1630,7 @@ private module Debug {
result = inferType(n, path)
}
Function debugResolveMethodCallExpr(MethodCallExpr mce) {
Function debugResolveMethodCallTarget(Call mce) {
mce = getRelevantLocatable() and
result = resolveMethodCallTarget(mce)
}

View File

@@ -1,49 +1,49 @@
multiplePathResolutions
| main.rs:1913:25:1913:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:25:1913:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:25:1913:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:25:1913:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:25:1913:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:25:1913:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:46:1913:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:46:1913:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:46:1913:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:46:1913:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:46:1913:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:46:1913:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:67:1913:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:67:1913:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:67:1913:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:67:1913:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:67:1913:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1913:67:1913:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:26:1916:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:26:1916:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:26:1916:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:26:1916:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:26:1916:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:26:1916:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:47:1916:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:47:1916:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:47:1916:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:47:1916:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:47:1916:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:47:1916:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:68:1916:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:68:1916:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:68:1916:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:68:1916:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:68:1916:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1916:68:1916:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1945:21:1945:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:25:1922:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:25:1922:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:25:1922:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:25:1922:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:25:1922:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:25:1922:36 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:46:1922:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:46:1922:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:46:1922:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:46:1922:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:46:1922:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:46:1922:57 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:67:1922:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:67:1922:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:67:1922:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:67:1922:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:67:1922:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1922:67:1922:78 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:26:1925:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:26:1925:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:26:1925:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:26:1925:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:26:1925:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:26:1925:37 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:47:1925:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:47:1925:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:47:1925:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:47:1925:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:47:1925:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:47:1925:58 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:68:1925:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:68:1925:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:68:1925:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:68:1925:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:68:1925:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1925:68:1925:79 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:1954:21:1954:29 | ...::from | file://:0:0:0:0 | fn from |

View File

@@ -1325,6 +1325,11 @@ mod overloadable_operators {
x: i64,
y: i64,
}
impl Default for Vec2 {
fn default() -> Self {
Vec2 { x: 0, y: 0 }
}
}
// Implement all overloadable operators for Vec2
impl Add for Vec2 {
type Output = Self;
@@ -1671,6 +1676,10 @@ mod overloadable_operators {
// Prefix operators
let vec2_neg = -v1; // $ type=vec2_neg:Vec2 method=Vec2::neg
let vec2_not = !v1; // $ type=vec2_not:Vec2 method=Vec2::not
// Here the type of `default_vec2` must be inferred from the `+` call.
let default_vec2 = Default::default(); // $ type=default_vec2:Vec2
let vec2_zero_plus = Vec2 { x: 0, y: 0 } + default_vec2; // $ method=Vec2::add
}
}