mirror of
https://github.com/github/codeql.git
synced 2026-04-22 23:35:14 +02:00
Merge branch 'main' into typeinfer
This commit is contained in:
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -26,6 +26,8 @@ private module MyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module MyFlow = TaintTracking::Global<MyConfig>;
|
||||
|
||||
@@ -36,6 +36,8 @@ private module MyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module MyFlow = TaintTracking::Global<MyConfig>;
|
||||
|
||||
@@ -27,6 +27,8 @@ private module MyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module MyFlow = TaintTracking::Global<MyConfig>;
|
||||
|
||||
@@ -26,6 +26,8 @@ private module MyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module MyFlow = TaintTracking::Global<MyConfig>;
|
||||
|
||||
@@ -36,6 +36,8 @@ private module MyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module MyFlow = TaintTracking::Global<MyConfig>;
|
||||
|
||||
@@ -27,6 +27,8 @@ private module MyConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module MyFlow = TaintTracking::Global<MyConfig>;
|
||||
|
||||
@@ -50,6 +50,8 @@ module WordexpTaintConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
}
|
||||
|
||||
module WordexpTaint = TaintTracking::Global<WordexpTaintConfig>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @id go/duplicate-branches
|
||||
* @tags maintainability
|
||||
* @tags quality
|
||||
* reliability
|
||||
* correctness
|
||||
* external/cwe/cwe-561
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -101,6 +101,8 @@ module UntrustedToTemplateExecWithConversionConfig implements DataFlow::StateCon
|
||||
conversion.getType().getUnderlyingType*() = unescapedType
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
module UntrustedToTemplateExecWithConversionFlow =
|
||||
|
||||
@@ -27,6 +27,8 @@ module Config implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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".
|
||||
@@ -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>;
|
||||
|
||||
@@ -47,6 +47,8 @@ module Config implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,10 @@ module ApkInstallationConfig implements DataFlow::ConfigSig {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module ApkInstallationFlow = DataFlow::Global<ApkInstallationConfig>;
|
||||
|
||||
@@ -49,6 +49,8 @@ module HardcodedCredentialApiCallConfig implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
n.asExpr().(MethodCall).getMethod() instanceof MethodSystemGetenv
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,8 @@ module HttpStringToUrlOpenMethodFlowConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Removed `encodeURI` and `escape` functions from the sanitizer list for request forgery.
|
||||
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. |
|
||||
@@ -0,0 +1 @@
|
||||
queries/overlay/InlineOverlayCaller.ql
|
||||
14
ql/ql/test/queries/overlay/InlineOverlayCaller/Test.qll
Normal file
14
ql/ql/test/queries/overlay/InlineOverlayCaller/Test.qll
Normal 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 }
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -4,4 +4,6 @@
|
||||
|
||||
private import internal.CallImpl
|
||||
|
||||
final class ArgumentPosition = Impl::ArgumentPosition;
|
||||
|
||||
final class Call = Impl::Call;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user