mirror of
https://github.com/github/codeql.git
synced 2026-06-19 11:51:08 +02:00
Compare commits
1 Commits
bazookamus
...
copilot/ql
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49df5bda0d |
@@ -2,7 +2,7 @@
|
||||
* @github/code-scanning-alert-coverage
|
||||
|
||||
# CodeQL language libraries
|
||||
/actions/ @github/code-scanning-alert-coverage
|
||||
/actions/ @github/codeql-dynamic
|
||||
/cpp/ @github/codeql-c-analysis
|
||||
/csharp/ @github/codeql-csharp
|
||||
/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor @github/code-scanning-language-coverage
|
||||
@@ -59,5 +59,9 @@ MODULE.bazel @github/codeql-ci-reviewers
|
||||
/.github/workflows/rust.yml @github/codeql-rust
|
||||
/.github/workflows/swift.yml @github/codeql-swift
|
||||
|
||||
# Misc
|
||||
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
|
||||
/misc/scripts/generate-code-scanning-query-list.py @RasmusWL
|
||||
|
||||
# .devcontainer
|
||||
/.devcontainer/ @github/codeql-ci-reviewers
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
## 0.4.36
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
@@ -1920,5 +1920,3 @@ private YamlMappingLikeNode resolveMatrixAccessPath(
|
||||
else result = resolveMatrixAccessPath(newRoot, rest)
|
||||
)
|
||||
}
|
||||
|
||||
class Comment = YamlComment;
|
||||
|
||||
@@ -52,12 +52,6 @@ private module YamlSig implements LibYaml::InputSig {
|
||||
class ParseErrorBase extends LocatableBase, @yaml_error {
|
||||
string getMessage() { yaml_errors(this, result) }
|
||||
}
|
||||
|
||||
class CommentBase extends LocatableBase, @yaml_comment {
|
||||
string getText() { yaml_comments(this, result, _) }
|
||||
|
||||
override string toString() { yaml_comments(this, _, result) }
|
||||
}
|
||||
}
|
||||
|
||||
import LibYaml::Make<YamlSig>
|
||||
|
||||
@@ -2,12 +2,10 @@ import actions
|
||||
|
||||
bindingset[runner]
|
||||
predicate isGithubHostedRunner(string runner) {
|
||||
// The list of github hosted repos:
|
||||
// https://github.com/actions/runner-images/blob/main/README.md#available-images
|
||||
// https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories
|
||||
runner.toLowerCase().regexpMatch("^ubuntu-([0-9.]+|latest|slim)(-arm)?$") or
|
||||
runner.toLowerCase().regexpMatch("^macos-([0-9]+|latest)(-x?large|-intel)?$") or
|
||||
runner.toLowerCase().regexpMatch("^windows-([0-9.]+|latest)(-vs[0-9.]+)?(-arm)?$")
|
||||
// list of github hosted repos: https://github.com/actions/runner-images/blob/main/README.md#available-images
|
||||
runner
|
||||
.toLowerCase()
|
||||
.regexpMatch("^(ubuntu-([0-9.]+|latest)|macos-([0-9]+|latest)(-x?large)?|windows-([0-9.]+|latest))$")
|
||||
}
|
||||
|
||||
bindingset[runner]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
## 0.6.28
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @name Checkout of untrusted code in a non-privileged context
|
||||
* @description Checking out and running the build script from a fork executes untrusted code. Even in a
|
||||
* non-privileged workflow, this can be abused, for example to compromise self-hosted runners
|
||||
* or to poison caches and artifacts that are later consumed by privileged workflows.
|
||||
* @name Checkout of untrusted code in a trusted context
|
||||
* @description Privileged workflows have read/write access to the base repository and access to secrets.
|
||||
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
|
||||
* that is able to push to the base repository and to access secrets.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
@@ -20,4 +20,4 @@ from PRHeadCheckoutStep checkout
|
||||
where
|
||||
// the checkout occurs in a non-privileged context
|
||||
inNonPrivilegedContext(checkout)
|
||||
select checkout, "Potential unsafe checkout of untrusted pull request on non-privileged workflow."
|
||||
select checkout, "Potential unsafe checkout of untrusted pull request on privileged workflow."
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
|
||||
@@ -15,4 +15,4 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-24.04-arm
|
||||
- ubuntu-22.04
|
||||
- ubuntu-22.04-arm
|
||||
- ubuntu-26.04
|
||||
- ubuntu-26.04-arm
|
||||
- ubuntu-slim
|
||||
- macos-26
|
||||
- macos-26-xlarge
|
||||
- macos-26-intel
|
||||
- macos-26-large
|
||||
- macos-latest-large
|
||||
- macos-15-large
|
||||
- macos-15
|
||||
- macos-15-intel
|
||||
- macos-latest
|
||||
- macos-15
|
||||
- macos-15-xlarge
|
||||
- macos-14-large
|
||||
- macos-14
|
||||
- macos-14-xlarge
|
||||
- windows-2025-vs2026
|
||||
- windows-latest
|
||||
- windows-2025
|
||||
- windows-2022
|
||||
- windows-11
|
||||
- windows-11-arm
|
||||
- windows-11-vs2026-arm
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: cmd
|
||||
@@ -1,10 +1,10 @@
|
||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Restructure and rename types related to operations.
|
||||
compatibility: full
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
@@ -9,7 +8,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
internal abstract class ElementAccess : Expression<ExpressionSyntax>
|
||||
{
|
||||
protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, BracketedArgumentListSyntax argumentList)
|
||||
: base(info.SetKind(GetKind(info.Context, info.Node, qualifier)))
|
||||
: base(info.SetKind(GetKind(info.Context, qualifier)))
|
||||
{
|
||||
this.qualifier = qualifier;
|
||||
this.argumentList = argumentList;
|
||||
@@ -18,125 +17,6 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private readonly ExpressionSyntax qualifier;
|
||||
private readonly BracketedArgumentListSyntax argumentList;
|
||||
|
||||
|
||||
private ISymbol? GetTargetSymbol()
|
||||
{
|
||||
return Context.GetSymbolInfo(base.Syntax).Symbol;
|
||||
}
|
||||
|
||||
private static void SetExprArgument(TextWriter trapFile, Expression left, Expression right)
|
||||
{
|
||||
trapFile.expr_argument(left, 0);
|
||||
trapFile.expr_argument(right, 0);
|
||||
}
|
||||
|
||||
private Expression MakeZeroFromEndExpression(IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var info = new ExpressionInfo(
|
||||
Context,
|
||||
AnnotatedTypeSymbol.CreateNotAnnotated(Context.Compilation.GetSpecialType(SpecialType.System_Int32)),
|
||||
Location,
|
||||
ExprKind.INDEX,
|
||||
parent,
|
||||
child,
|
||||
isCompilerGenerated: true,
|
||||
null);
|
||||
|
||||
var index = new Expression(info);
|
||||
|
||||
MakeZeroLiteral(index, 0);
|
||||
return index;
|
||||
}
|
||||
|
||||
private Expression MakeZeroLiteral(IExpressionParentEntity parent, int child)
|
||||
{
|
||||
return Literal.CreateGenerated(Context, parent, child, Context.Compilation.GetSpecialType(SpecialType.System_Int32), 0, Location);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// It is assumed that either the input is
|
||||
/// 1. A normal expression that can be used as endpoint (e.g a constant like "3").
|
||||
/// 2. An index expression indicating that we should read from the end (e.g "^1").
|
||||
/// </summary>
|
||||
/// <param name="syntax">The syntax node representing the range endpoint.</param>
|
||||
/// <param name="parent">The parent expression entity.</param>
|
||||
/// <param name="child">The child index within the parent.</param>
|
||||
/// <returns>An expression representing the endpoint of a range to be used in conjunction with a slice operation.</returns>
|
||||
private Expression MakeFromRangeEndpoint(ExpressionSyntax syntax, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var info = new ExpressionNodeInfo(Context, syntax, parent, child);
|
||||
|
||||
return syntax.Kind() == SyntaxKind.IndexExpression
|
||||
? PrefixUnary.Create(info.SetKind(ExprKind.INDEX))
|
||||
: Factory.Create(info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given method is a slice method, which is defined as a method with
|
||||
/// the name "Slice" or "Substring" and two parameters.
|
||||
/// </summary>
|
||||
/// <param name="method">The method symbol to check.</param>
|
||||
/// <returns>True if the method is a slice method; false otherwise.</returns>
|
||||
private bool IsSlice(IMethodSymbol method, out RangeExpressionSyntax? range)
|
||||
{
|
||||
range = null;
|
||||
|
||||
if (argumentList.Arguments.Count == 1)
|
||||
{
|
||||
range = argumentList.Arguments[0].Expression as RangeExpressionSyntax;
|
||||
}
|
||||
|
||||
return (method.Name == "Slice" || method.Name == "Substring")
|
||||
&& method.Parameters.Length == 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates a slice method call based on the given range.
|
||||
/// Roslyn translates indexer accesses with range expressions in the following way.
|
||||
/// 1. s[a..b] -> s.Slice(a, b - a)
|
||||
/// 2. s[..b] -> s.Slice(0, b)
|
||||
/// 3. s[a..] -> s.Slice(a, s.Length - a)
|
||||
/// 4. s[..] -> s.Slice(0, s.Length)
|
||||
/// However, it is possible that both the qualifier or the index endpoints may contain method calls.
|
||||
/// If we want to translate this accurately, we would need to introduce synthetic statements for qualifier and
|
||||
/// the endpoints, which should then be used in the slice method call.
|
||||
/// To avoid this, we translate as follows.
|
||||
/// 1. s[a..b] -> s.Slice(a, b)
|
||||
/// 2. s[..b] -> s.Slice(0, b)
|
||||
/// 3. s[a..] -> s.Slice(a, ^0)
|
||||
/// 4. s[..] -> s.Slice(0, ^0)
|
||||
///
|
||||
/// Even though index expressions can't technically be used in this way, they signal that we
|
||||
/// could perceive ^b as "length - b".
|
||||
///
|
||||
/// Call arguments are only populated when a range expression is directly available in
|
||||
/// the list of arguments.
|
||||
/// This means that cases like below are not handled.
|
||||
/// System.Range x = 1..3;
|
||||
/// s[x]
|
||||
/// </summary>
|
||||
/// <param name="trapFile">The trap file to write to.</param>
|
||||
/// <param name="slice">The slice method symbol.</param>
|
||||
/// <param name="range">The range expression syntax.</param>
|
||||
private void PopulateSlice(TextWriter trapFile, IMethodSymbol slice, RangeExpressionSyntax? range)
|
||||
{
|
||||
if (range is not null)
|
||||
{
|
||||
// Populate the call arguments
|
||||
var left = range.LeftOperand is ExpressionSyntax lsyntax
|
||||
? MakeFromRangeEndpoint(lsyntax, this, 0)
|
||||
: MakeZeroLiteral(this, 0);
|
||||
|
||||
var right = range.RightOperand is ExpressionSyntax rsyntax
|
||||
? MakeFromRangeEndpoint(rsyntax, this, 1)
|
||||
: MakeZeroFromEndExpression(this, 1);
|
||||
|
||||
SetExprArgument(trapFile, left, right);
|
||||
}
|
||||
trapFile.expr_call(this, Method.Create(Context, slice));
|
||||
}
|
||||
|
||||
protected override void PopulateExpression(TextWriter trapFile)
|
||||
{
|
||||
if (Kind == ExprKind.POINTER_INDIRECTION)
|
||||
@@ -150,19 +30,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
else
|
||||
{
|
||||
Create(Context, qualifier, this, -1);
|
||||
|
||||
var target = GetTargetSymbol();
|
||||
if (target is IMethodSymbol method && IsSlice(method, out var range))
|
||||
{
|
||||
// When an indexer on a span or string is used in conjunction with a range expression, the compiler translates
|
||||
// this into a call to the "Slice" or "Substring" method.
|
||||
// In this case, we want to populate a slice/substring method call instead of an indexer access.
|
||||
PopulateSlice(trapFile, method, range);
|
||||
return;
|
||||
}
|
||||
|
||||
PopulateArguments(trapFile, argumentList, 0);
|
||||
if (target is IPropertySymbol { IsIndexer: true } indexer)
|
||||
|
||||
var symbolInfo = Context.GetSymbolInfo(base.Syntax);
|
||||
|
||||
if (symbolInfo.Symbol is IPropertySymbol indexer)
|
||||
{
|
||||
trapFile.expr_access(this, Indexer.Create(Context, indexer));
|
||||
}
|
||||
@@ -174,11 +46,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private static bool IsArray(ITypeSymbol symbol) =>
|
||||
symbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array || symbol.IsInlineArray();
|
||||
|
||||
private static ExprKind GetKind(Context cx, ExpressionSyntax syntax, ExpressionSyntax qualifier)
|
||||
private static ExprKind GetKind(Context cx, ExpressionSyntax qualifier)
|
||||
{
|
||||
if (cx.GetSymbolInfo(syntax).Symbol is IMethodSymbol)
|
||||
return ExprKind.METHOD_INVOCATION;
|
||||
|
||||
var qualifierType = cx.GetType(qualifier);
|
||||
|
||||
// This is a compilation error, so make a guess and continue.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved extraction of range-access expressions on spans and strings (for example, `a[0..3]`). These expressions are now extracted as `Slice` (span) or `Substring` (string) calls.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved property and indexer call target resolution for partially overridden properties and indexers.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added Razor Page handler method parameters (e.g., `OnGet`, `OnPost`, `OnPostAsync`) as remote flow sources, enabling security queries such as `cs/sql-injection` to detect vulnerabilities in `PageModel` subclasses.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.
|
||||
@@ -50,15 +50,15 @@ private predicate maybeUsedInElfHashFunction(Variable v, Operation xor, Operatio
|
||||
|
|
||||
add instanceof AddOperation and
|
||||
e1.getAChild*() = add.getAnOperand() and
|
||||
e1 instanceof BinaryBitwiseExpr and
|
||||
e2 = e1.(BinaryBitwiseExpr).getLeftOperand() and
|
||||
e1 instanceof BinaryBitwiseOperation and
|
||||
e2 = e1.(BinaryBitwiseOperation).getLeftOperand() and
|
||||
v = addAssign.getTargetVariable() and
|
||||
addAssign.getAChild*() = add and
|
||||
(xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and
|
||||
addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and
|
||||
xorAssign.getAChild*() = xor and
|
||||
v = xorAssign.getTargetVariable() and
|
||||
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseExpr) and
|
||||
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseOperation) and
|
||||
xor.getControlFlowNode().getASuccessor*() = notOp.getControlFlowNode() and
|
||||
notAssign.getAChild*() = notOp and
|
||||
v = notAssign.getTargetVariable() and
|
||||
|
||||
@@ -290,7 +290,7 @@ module AssignableInternal {
|
||||
newtype TAssignableDefinition =
|
||||
TAssignmentDefinition(Assignment a) {
|
||||
not a.getLeftOperand() instanceof TupleExpr and
|
||||
not a instanceof AssignCallExpr and
|
||||
not a instanceof AssignCallOperation and
|
||||
not a instanceof AssignCoalesceExpr
|
||||
} or
|
||||
TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or
|
||||
@@ -324,7 +324,7 @@ module AssignableInternal {
|
||||
TAddressOfDefinition(AddressOfExpr aoe) or
|
||||
TPatternDefinition(TopLevelPatternDecl tlpd) or
|
||||
TAssignOperationDefinition(AssignOperation ao) {
|
||||
ao instanceof AssignCallExpr and not ao instanceof CompoundAssignmentOperatorCall
|
||||
ao instanceof AssignCallOperation and not ao instanceof CompoundAssignmentOperatorCall
|
||||
or
|
||||
ao instanceof AssignCoalesceExpr
|
||||
}
|
||||
|
||||
@@ -57,28 +57,6 @@ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelE
|
||||
/** Gets the `set` accessor of this declaration, if any. */
|
||||
Setter getSetter() { result = this.getAnAccessor() }
|
||||
|
||||
/** Gets the target accessor of this declaration when used in a read context, if any. */
|
||||
Accessor getReadTarget() {
|
||||
result = this.getGetter()
|
||||
or
|
||||
not exists(this.getGetter()) and
|
||||
result = this.getOverridee().getReadTarget()
|
||||
}
|
||||
|
||||
/** Gets the target accessor of this declaration when used in a write context, if any. */
|
||||
Accessor getWriteTarget() {
|
||||
result = this.getSetter()
|
||||
or
|
||||
not exists(this.getSetter()) and
|
||||
result = this.getOverridee().getWriteTarget()
|
||||
or
|
||||
result =
|
||||
any(Getter g |
|
||||
g = this.getReadTarget() and
|
||||
g.getAnnotatedReturnType().isRef()
|
||||
)
|
||||
}
|
||||
|
||||
override DeclarationWithGetSetAccessors getOverridee() {
|
||||
result = DeclarationWithAccessors.super.getOverridee()
|
||||
}
|
||||
|
||||
@@ -912,17 +912,18 @@ module Internal {
|
||||
)
|
||||
or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
result =
|
||||
any(BinaryArithmeticOperation bao |
|
||||
exists(Expr o |
|
||||
bao.getAnOperand() = e and
|
||||
bao.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
nonNullValueImplied(o) and
|
||||
e != o
|
||||
)
|
||||
)
|
||||
exists(BinaryOperation bo, Expr o |
|
||||
bo instanceof BinaryArithmeticOperation or
|
||||
bo instanceof AssignArithmeticOperation
|
||||
|
|
||||
result = bo and
|
||||
bo.getAnOperand() = e and
|
||||
bo.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
nonNullValueImplied(o) and
|
||||
e != o
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -933,10 +934,10 @@ module Internal {
|
||||
any(QualifiableExpr qe |
|
||||
qe.isConditional() and
|
||||
result = qe.getQualifier()
|
||||
)
|
||||
or
|
||||
) or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand())
|
||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand()) or
|
||||
e = any(AssignArithmeticOperation aao | result = aao.getAnOperand())
|
||||
}
|
||||
|
||||
deprecated predicate isGuard(Expr e, GuardValue val) {
|
||||
|
||||
@@ -172,10 +172,6 @@ module Ast implements AstSig<Location> {
|
||||
|
||||
class DoStmt = CS::DoStmt;
|
||||
|
||||
class UntilStmt extends LoopStmt {
|
||||
UntilStmt() { none() }
|
||||
}
|
||||
|
||||
final private class FinalForStmt = CS::ForStmt;
|
||||
|
||||
class ForStmt extends FinalForStmt {
|
||||
@@ -207,7 +203,7 @@ module Ast implements AstSig<Location> {
|
||||
final private class FinalTryStmt = CS::TryStmt;
|
||||
|
||||
class TryStmt extends FinalTryStmt {
|
||||
AstNode getBody(int index) { index = 0 and result = this.getBlock() }
|
||||
Stmt getBody() { result = this.getBlock() }
|
||||
|
||||
CatchClause getCatch(int index) { result = this.getCatchClause(index) }
|
||||
|
||||
|
||||
@@ -124,7 +124,9 @@ private module Internal {
|
||||
TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or
|
||||
TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or
|
||||
TDispatchDynamicElementAccess(DynamicElementAccess dea) or
|
||||
TDispatchDynamicEventAccess(AssignArithmeticExpr aao, DynamicMemberAccess dma, string name) {
|
||||
TDispatchDynamicEventAccess(
|
||||
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||
) {
|
||||
isPotentialEventCall(aao, dma, name)
|
||||
} or
|
||||
TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or
|
||||
@@ -228,7 +230,7 @@ private module Internal {
|
||||
* accessor.
|
||||
*/
|
||||
private predicate isPotentialEventCall(
|
||||
AssignArithmeticExpr aao, DynamicMemberAccess dma, string name
|
||||
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||
) {
|
||||
aao instanceof DynamicOperatorCall and
|
||||
dma = aao.getLeftOperand() and
|
||||
@@ -1395,7 +1397,9 @@ private module Internal {
|
||||
private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall,
|
||||
TDispatchDynamicEventAccess
|
||||
{
|
||||
override AssignArithmeticExpr getCall() { this = TDispatchDynamicEventAccess(result, _, _) }
|
||||
override AssignArithmeticOperation getCall() {
|
||||
this = TDispatchDynamicEventAccess(result, _, _)
|
||||
}
|
||||
|
||||
override string getName() { this = TDispatchDynamicEventAccess(_, _, result) }
|
||||
|
||||
|
||||
@@ -11,27 +11,19 @@ import Expr
|
||||
* (`UnaryArithmeticOperation`) or a binary arithmetic operation
|
||||
* (`BinaryArithmeticOperation`).
|
||||
*/
|
||||
class ArithmeticOperation extends Operation, @arith_operation {
|
||||
class ArithmeticOperation extends Operation, @arith_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary arithmetic operation. Either a binary arithmetic expression (`BinaryArithmeticExpr`) or
|
||||
* an arithmetic assignment expression (`AssignArithmeticExpr`).
|
||||
*/
|
||||
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_operation {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary arithmetic operation. Either a unary minus expression
|
||||
* (`UnaryMinusExpr`), a unary plus expression (`UnaryPlusExpr`),
|
||||
* A unary arithmetic operation. Either a unary minus operation
|
||||
* (`UnaryMinusExpr`), a unary plus operation (`UnaryPlusExpr`),
|
||||
* or a mutator operation (`MutatorOperation`).
|
||||
*/
|
||||
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_operation { }
|
||||
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_op_expr { }
|
||||
|
||||
/**
|
||||
* A unary minus expression, for example `-x`.
|
||||
* A unary minus operation, for example `-x`.
|
||||
*/
|
||||
class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
||||
override string getOperator() { result = "-" }
|
||||
@@ -40,7 +32,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary plus expression, for example `+x`.
|
||||
* A unary plus operation, for example `+x`.
|
||||
*/
|
||||
class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
||||
override string getOperator() { result = "+" }
|
||||
@@ -52,40 +44,40 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
||||
* A mutator operation. Either an increment operation (`IncrementOperation`)
|
||||
* or a decrement operation (`DecrementOperation`).
|
||||
*/
|
||||
class MutatorOperation extends UnaryArithmeticOperation, @mut_operation { }
|
||||
class MutatorOperation extends UnaryArithmeticOperation, @mut_op_expr { }
|
||||
|
||||
/**
|
||||
* An increment operation. Either a postfix increment expression
|
||||
* (`PostIncrExpr`) or a prefix increment expression (`PreIncrExpr`).
|
||||
* An increment operation. Either a postfix increment operation
|
||||
* (`PostIncrExpr`) or a prefix increment operation (`PreIncrExpr`).
|
||||
*/
|
||||
class IncrementOperation extends MutatorOperation, @incr_operation {
|
||||
class IncrementOperation extends MutatorOperation, @incr_op_expr {
|
||||
override string getOperator() { result = "++" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A decrement operation. Either a postfix decrement expression
|
||||
* (`PostDecrExpr`) or a prefix decrement expression (`PreDecrExpr`).
|
||||
* A decrement operation. Either a postfix decrement operation
|
||||
* (`PostDecrExpr`) or a prefix decrement operation (`PreDecrExpr`).
|
||||
*/
|
||||
class DecrementOperation extends MutatorOperation, @decr_operation {
|
||||
class DecrementOperation extends MutatorOperation, @decr_op_expr {
|
||||
override string getOperator() { result = "--" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix increment expression, for example `++x`.
|
||||
* A prefix increment operation, for example `++x`.
|
||||
*/
|
||||
class PreIncrExpr extends IncrementOperation, @pre_incr_expr {
|
||||
override string getAPrimaryQlClass() { result = "PreIncrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix decrement expression, for example `--x`.
|
||||
* A prefix decrement operation, for example `--x`.
|
||||
*/
|
||||
class PreDecrExpr extends DecrementOperation, @pre_decr_expr {
|
||||
override string getAPrimaryQlClass() { result = "PreDecrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A postfix increment expression, for example `x++`.
|
||||
* A postfix increment operation, for example `x++`.
|
||||
*/
|
||||
class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
||||
override string toString() { result = "..." + this.getOperator() }
|
||||
@@ -94,7 +86,7 @@ class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A postfix decrement expression, for example `x--`.
|
||||
* A postfix decrement operation, for example `x--`.
|
||||
*/
|
||||
class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
||||
override string toString() { result = "..." + this.getOperator() }
|
||||
@@ -103,84 +95,55 @@ class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* An addition operation, either `x + y` or `x += y`.
|
||||
* A binary arithmetic operation. Either an addition operation
|
||||
* (`AddExpr`), a subtraction operation (`SubExpr`), a multiplication
|
||||
* operation (`MulExpr`), a division operation (`DivExpr`), or a
|
||||
* remainder operation (`RemExpr`).
|
||||
*/
|
||||
class AddOperation extends BinaryArithmeticOperation, @add_operation { }
|
||||
|
||||
/**
|
||||
* A subtraction operation, either `x - y` or `x -= y`.
|
||||
*/
|
||||
class SubOperation extends BinaryArithmeticOperation, @sub_operation { }
|
||||
|
||||
/**
|
||||
* A multiplication operation, either `x * y` or `x *= y`.
|
||||
*/
|
||||
class MulOperation extends BinaryArithmeticOperation, @mul_operation { }
|
||||
|
||||
/**
|
||||
* A division operation, either `x / y` or `x /= y`.
|
||||
*/
|
||||
class DivOperation extends BinaryArithmeticOperation, @div_operation {
|
||||
/** Gets the numerator of this division operation. */
|
||||
Expr getNumerator() { result = this.getLeftOperand() }
|
||||
|
||||
/** Gets the denominator of this division operation. */
|
||||
Expr getDenominator() { result = this.getRightOperand() }
|
||||
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder operation, either `x % y` or `x %= y`.
|
||||
* An addition operation, for example `x + y`.
|
||||
*/
|
||||
class RemOperation extends BinaryArithmeticOperation, @rem_operation { }
|
||||
|
||||
/**
|
||||
* A binary arithmetic expression. Either an addition expression
|
||||
* (`AddExpr`), a subtraction expression (`SubExpr`), a multiplication
|
||||
* expression (`MulExpr`), a division expression (`DivExpr`), or a
|
||||
* remainder expression (`RemExpr`).
|
||||
*/
|
||||
class BinaryArithmeticExpr extends BinaryArithmeticOperation, @bin_arith_expr { }
|
||||
|
||||
/**
|
||||
* An addition expression, for example `x + y`.
|
||||
*/
|
||||
class AddExpr extends BinaryArithmeticExpr, AddOperation, @add_expr {
|
||||
class AddExpr extends BinaryArithmeticOperation, AddOperation, @add_expr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AddExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A subtraction expression, for example `x - y`.
|
||||
* A subtraction operation, for example `x - y`.
|
||||
*/
|
||||
class SubExpr extends BinaryArithmeticExpr, SubOperation, @sub_expr {
|
||||
class SubExpr extends BinaryArithmeticOperation, SubOperation, @sub_expr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SubExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A multiplication expression, for example `x * y`.
|
||||
* A multiplication operation, for example `x * y`.
|
||||
*/
|
||||
class MulExpr extends BinaryArithmeticExpr, MulOperation, @mul_expr {
|
||||
class MulExpr extends BinaryArithmeticOperation, MulOperation, @mul_expr {
|
||||
override string getOperator() { result = "*" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MulExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A division expression, for example `x / y`.
|
||||
* A division operation, for example `x / y`.
|
||||
*/
|
||||
class DivExpr extends BinaryArithmeticExpr, DivOperation, @div_expr {
|
||||
class DivExpr extends BinaryArithmeticOperation, DivOperation, @div_expr {
|
||||
override string getOperator() { result = "/" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DivExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder expression, for example `x % y`.
|
||||
* A remainder operation, for example `x % y`.
|
||||
*/
|
||||
class RemExpr extends BinaryArithmeticExpr, RemOperation, @rem_expr {
|
||||
class RemExpr extends BinaryArithmeticOperation, RemOperation, @rem_expr {
|
||||
override string getOperator() { result = "%" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RemExpr" }
|
||||
|
||||
@@ -72,9 +72,9 @@ class AssignExpr extends Assignment, @simple_assign_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* An assignment operation. Either an arithmetic assignment expression
|
||||
* (`AssignArithmeticExpr`), a bitwise assignment expression
|
||||
* (`AssignBitwiseExpr`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||
* An assignment operation. Either an arithmetic assignment operation
|
||||
* (`AssignArithmeticOperation`), a bitwise assignment operation
|
||||
* (`AssignBitwiseOperation`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||
* a null-coalescing assignment (`AssignCoalesceExpr`).
|
||||
*/
|
||||
class AssignOperation extends Assignment, @assign_op_expr {
|
||||
@@ -94,147 +94,134 @@ class AssignOperation extends Assignment, @assign_op_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A compound assignment expression that invokes an operator.
|
||||
* A compound assignment operation that invokes an operator.
|
||||
*
|
||||
* (1) `x += y` invokes the compound assignment operator `+=` (if it exists).
|
||||
* (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`.
|
||||
*
|
||||
* Either an arithmetic assignment expression (`AssignArithmeticExpr`) or a bitwise
|
||||
* assignment expression (`AssignBitwiseExpr`).
|
||||
* Either an arithmetic assignment operation (`AssignArithmeticOperation`) or a bitwise
|
||||
* assignment operation (`AssignBitwiseOperation`).
|
||||
*/
|
||||
class AssignCallExpr extends AssignOperation, OperatorCall, QualifiableExpr, @assign_op_call_expr {
|
||||
class AssignCallOperation extends AssignOperation, OperatorCall, QualifiableExpr,
|
||||
@assign_op_call_expr
|
||||
{
|
||||
override string toString() { result = AssignOperation.super.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AssignCallExpr` instead.
|
||||
*/
|
||||
deprecated class AssignCallOperation = AssignCallExpr;
|
||||
|
||||
/**
|
||||
* An arithmetic assignment expression. Either an addition assignment expression
|
||||
* (`AssignAddExpr`), a subtraction assignment expression (`AssignSubExpr`), a
|
||||
* multiplication assignment expression (`AssignMulExpr`), a division assignment
|
||||
* expression (`AssignDivExpr`), or a remainder assignment expression
|
||||
* An arithmetic assignment operation. Either an addition assignment operation
|
||||
* (`AssignAddExpr`), a subtraction assignment operation (`AssignSubExpr`), a
|
||||
* multiplication assignment operation (`AssignMulExpr`), a division assignment
|
||||
* operation (`AssignDivExpr`), or a remainder assignment operation
|
||||
* (`AssignRemExpr`).
|
||||
*/
|
||||
class AssignArithmeticExpr extends AssignCallExpr, @assign_arith_expr { }
|
||||
class AssignArithmeticOperation extends AssignCallOperation, @assign_arith_expr { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AssignArithmeticExpr` instead.
|
||||
* An addition assignment operation, for example `x += y`.
|
||||
*/
|
||||
deprecated class AssignArithmeticOperation = AssignArithmeticExpr;
|
||||
|
||||
/**
|
||||
* An addition assignment expression, for example `x += y`.
|
||||
*/
|
||||
class AssignAddExpr extends AssignArithmeticExpr, AddOperation, @assign_add_expr {
|
||||
class AssignAddExpr extends AssignArithmeticOperation, AddOperation, @assign_add_expr {
|
||||
override string getOperator() { result = "+=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A subtraction assignment expression, for example `x -= y`.
|
||||
* A subtraction assignment operation, for example `x -= y`.
|
||||
*/
|
||||
class AssignSubExpr extends AssignArithmeticExpr, SubOperation, @assign_sub_expr {
|
||||
class AssignSubExpr extends AssignArithmeticOperation, SubOperation, @assign_sub_expr {
|
||||
override string getOperator() { result = "-=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A multiplication assignment expression, for example `x *= y`.
|
||||
* An multiplication assignment operation, for example `x *= y`.
|
||||
*/
|
||||
class AssignMulExpr extends AssignArithmeticExpr, MulOperation, @assign_mul_expr {
|
||||
class AssignMulExpr extends AssignArithmeticOperation, MulOperation, @assign_mul_expr {
|
||||
override string getOperator() { result = "*=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A division assignment expression, for example `x /= y`.
|
||||
* An division assignment operation, for example `x /= y`.
|
||||
*/
|
||||
class AssignDivExpr extends AssignArithmeticExpr, DivOperation, @assign_div_expr {
|
||||
class AssignDivExpr extends AssignArithmeticOperation, DivOperation, @assign_div_expr {
|
||||
override string getOperator() { result = "/=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder assignment expression, for example `x %= y`.
|
||||
* A remainder assignment operation, for example `x %= y`.
|
||||
*/
|
||||
class AssignRemExpr extends AssignArithmeticExpr, RemOperation, @assign_rem_expr {
|
||||
class AssignRemExpr extends AssignArithmeticOperation, RemOperation, @assign_rem_expr {
|
||||
override string getOperator() { result = "%=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise assignment expression. Either a bitwise-and assignment
|
||||
* expression (`AssignAndExpr`), a bitwise-or assignment
|
||||
* expression (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||
* expression (`AssignXorExpr`), a left-shift assignment
|
||||
* expression (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||
* expression (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||
* expression (`AssignUnsignedRightShiftExpr`).
|
||||
* A bitwise assignment operation. Either a bitwise-and assignment
|
||||
* operation (`AssignAndExpr`), a bitwise-or assignment
|
||||
* operation (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||
* operation (`AssignXorExpr`), a left-shift assignment
|
||||
* operation (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||
* operation (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||
* operation (`AssignUnsignedRightShiftExpr`).
|
||||
*/
|
||||
class AssignBitwiseExpr extends AssignCallExpr, @assign_bitwise_expr { }
|
||||
class AssignBitwiseOperation extends AssignCallOperation, @assign_bitwise_expr { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AssignBitwiseExpr` instead.
|
||||
* A bitwise-and assignment operation, for example `x &= y`.
|
||||
*/
|
||||
deprecated class AssignBitwiseOperation = AssignBitwiseExpr;
|
||||
|
||||
/**
|
||||
* A bitwise-and assignment expression, for example `x &= y`.
|
||||
*/
|
||||
class AssignAndExpr extends AssignBitwiseExpr, BitwiseAndOperation, @assign_and_expr {
|
||||
class AssignAndExpr extends AssignBitwiseOperation, BitwiseAndOperation, @assign_and_expr {
|
||||
override string getOperator() { result = "&=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-or assignment expression, for example `x |= y`.
|
||||
* A bitwise-or assignment operation, for example `x |= y`.
|
||||
*/
|
||||
class AssignOrExpr extends AssignBitwiseExpr, BitwiseOrOperation, @assign_or_expr {
|
||||
class AssignOrExpr extends AssignBitwiseOperation, BitwiseOrOperation, @assign_or_expr {
|
||||
override string getOperator() { result = "|=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or assignment expression, for example `x ^= y`.
|
||||
* A bitwise exclusive-or assignment operation, for example `x ^= y`.
|
||||
*/
|
||||
class AssignXorExpr extends AssignBitwiseExpr, BitwiseXorOperation, @assign_xor_expr {
|
||||
class AssignXorExpr extends AssignBitwiseOperation, BitwiseXorOperation, @assign_xor_expr {
|
||||
override string getOperator() { result = "^=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A left-shift assignment expression, for example `x <<= y`.
|
||||
* A left-shift assignment operation, for example `x <<= y`.
|
||||
*/
|
||||
class AssignLeftShiftExpr extends AssignBitwiseExpr, LeftShiftOperation, @assign_lshift_expr {
|
||||
class AssignLeftShiftExpr extends AssignBitwiseOperation, LeftShiftOperation, @assign_lshift_expr {
|
||||
override string getOperator() { result = "<<=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignLeftShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A right-shift assignment expression, for example `x >>= y`.
|
||||
* A right-shift assignment operation, for example `x >>= y`.
|
||||
*/
|
||||
class AssignRightShiftExpr extends AssignBitwiseExpr, RightShiftOperation, @assign_rshift_expr {
|
||||
class AssignRightShiftExpr extends AssignBitwiseOperation, RightShiftOperation, @assign_rshift_expr {
|
||||
override string getOperator() { result = ">>=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignRightShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unsigned right-shift assignment expression, for example `x >>>= y`.
|
||||
* An unsigned right-shift assignment operation, for example `x >>>= y`.
|
||||
*/
|
||||
class AssignUnsignedRightShiftExpr extends AssignBitwiseExpr, UnsignedRightShiftOperation,
|
||||
class AssignUnsignedRightShiftExpr extends AssignBitwiseOperation, UnsignedRightShiftOperation,
|
||||
@assign_urshift_expr
|
||||
{
|
||||
override string getOperator() { result = ">>>=" }
|
||||
@@ -310,10 +297,10 @@ class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A null-coalescing assignment expression, for example `x ??= y`.
|
||||
* A null-coalescing assignment operation, for example `x ??= y`.
|
||||
*/
|
||||
class AssignCoalesceExpr extends AssignOperation, NullCoalescingOperation, @assign_coalesce_expr {
|
||||
override string getOperator() { result = "??=" }
|
||||
override string toString() { result = "... ??= ..." }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
|
||||
}
|
||||
|
||||
@@ -10,16 +10,16 @@ import Expr
|
||||
* A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`)
|
||||
* or a binary bitwise operation (`BinaryBitwiseOperation`).
|
||||
*/
|
||||
class BitwiseOperation extends Operation, @bit_operation { }
|
||||
class BitwiseOperation extends Operation, @bit_expr { }
|
||||
|
||||
/**
|
||||
* A unary bitwise operation, that is, a bitwise complement operation
|
||||
* (`ComplementExpr`).
|
||||
*/
|
||||
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_operation { }
|
||||
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_op_expr { }
|
||||
|
||||
/**
|
||||
* A bitwise complement expression, for example `~x`.
|
||||
* A bitwise complement operation, for example `~x`.
|
||||
*/
|
||||
class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
||||
override string getOperator() { result = "~" }
|
||||
@@ -28,101 +28,67 @@ class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary bitwise operation. Either a binary bitwise expression (`BinaryBitwiseExpr`) or
|
||||
* a bitwise assignment expression (`AssignBitwiseExpr`).
|
||||
* A binary bitwise operation. Either a bitwise-and operation
|
||||
* (`BitwiseAndExpr`), a bitwise-or operation (`BitwiseOrExpr`),
|
||||
* a bitwise exclusive-or operation (`BitwiseXorExpr`), a left-shift
|
||||
* operation (`LeftShiftExpr`), a right-shift operation (`RightShiftExpr`),
|
||||
* or an unsigned right-shift operation (`UnsignedRightShiftExpr`).
|
||||
*/
|
||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_operation {
|
||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-and operation, either `x & y` or `x &= y`.
|
||||
* A left-shift operation, for example `x << y`.
|
||||
*/
|
||||
class BitwiseAndOperation extends BinaryBitwiseOperation, @and_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise-or operation, either `x | y` or `x |= y`.
|
||||
*/
|
||||
class BitwiseOrOperation extends BinaryBitwiseOperation, @or_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
|
||||
*/
|
||||
class BitwiseXorOperation extends BinaryBitwiseOperation, @xor_operation { }
|
||||
|
||||
/**
|
||||
* A left-shift operation, either `x << y` or `x <<= y`.
|
||||
*/
|
||||
class LeftShiftOperation extends BinaryBitwiseOperation, @lshift_operation { }
|
||||
|
||||
/**
|
||||
* A right-shift operation, either `x >> y` or `x >>= y`.
|
||||
*/
|
||||
class RightShiftOperation extends BinaryBitwiseOperation, @rshift_operation { }
|
||||
|
||||
/**
|
||||
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
|
||||
*/
|
||||
class UnsignedRightShiftOperation extends BinaryBitwiseOperation, @urshift_operation { }
|
||||
|
||||
/**
|
||||
* A binary bitwise expression. Either a bitwise-and expression
|
||||
* (`BitwiseAndExpr`), a bitwise-or expression (`BitwiseOrExpr`),
|
||||
* a bitwise exclusive-or expression (`BitwiseXorExpr`), a left-shift
|
||||
* expression (`LeftShiftExpr`), a right-shift expression (`RightShiftExpr`),
|
||||
* or an unsigned right-shift expression (`UnsignedRightShiftExpr`).
|
||||
*/
|
||||
class BinaryBitwiseExpr extends BinaryBitwiseOperation, @bin_bit_expr { }
|
||||
|
||||
/**
|
||||
* A left-shift expression, for example `x << y`.
|
||||
*/
|
||||
class LeftShiftExpr extends BinaryBitwiseExpr, LeftShiftOperation, @lshift_expr {
|
||||
class LeftShiftExpr extends BinaryBitwiseOperation, LeftShiftOperation, @lshift_expr {
|
||||
override string getOperator() { result = "<<" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LeftShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A right-shift expression, for example `x >> y`.
|
||||
* A right-shift operation, for example `x >> y`.
|
||||
*/
|
||||
class RightShiftExpr extends BinaryBitwiseExpr, RightShiftOperation, @rshift_expr {
|
||||
class RightShiftExpr extends BinaryBitwiseOperation, RightShiftOperation, @rshift_expr {
|
||||
override string getOperator() { result = ">>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RightShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unsigned right-shift expression, for example `x >>> y`.
|
||||
* An unsigned right-shift operation, for example `x >>> y`.
|
||||
*/
|
||||
class UnsignedRightShiftExpr extends BinaryBitwiseExpr, UnsignedRightShiftOperation, @urshift_expr {
|
||||
class UnsignedRightShiftExpr extends BinaryBitwiseOperation, UnsignedRightShiftOperation,
|
||||
@urshift_expr
|
||||
{
|
||||
override string getOperator() { result = ">>>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-and expression, for example `x & y`.
|
||||
* A bitwise-and operation, for example `x & y`.
|
||||
*/
|
||||
class BitwiseAndExpr extends BinaryBitwiseExpr, BitwiseAndOperation, @bit_and_expr {
|
||||
class BitwiseAndExpr extends BinaryBitwiseOperation, BitwiseAndOperation, @bit_and_expr {
|
||||
override string getOperator() { result = "&" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-or expression, for example `x | y`.
|
||||
* A bitwise-or operation, for example `x | y`.
|
||||
*/
|
||||
class BitwiseOrExpr extends BinaryBitwiseExpr, BitwiseOrOperation, @bit_or_expr {
|
||||
class BitwiseOrExpr extends BinaryBitwiseOperation, BitwiseOrOperation, @bit_or_expr {
|
||||
override string getOperator() { result = "|" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or expression, for example `x ^ y`.
|
||||
* A bitwise exclusive-or operation, for example `x ^ y`.
|
||||
*/
|
||||
class BitwiseXorExpr extends BinaryBitwiseExpr, BitwiseXorOperation, @bit_xor_expr {
|
||||
class BitwiseXorExpr extends BinaryBitwiseOperation, BitwiseXorOperation, @bit_xor_expr {
|
||||
override string getOperator() { result = "^" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||
|
||||
@@ -609,7 +609,7 @@ class InstanceMutatorOperatorCall extends MutatorOperatorCall {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CompoundAssignmentOperatorCall extends AssignCallExpr {
|
||||
class CompoundAssignmentOperatorCall extends AssignCallOperation {
|
||||
CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator }
|
||||
|
||||
override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 }
|
||||
@@ -762,12 +762,20 @@ class AccessorCall extends Call, QualifiableExpr, @call_access_expr {
|
||||
*/
|
||||
class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
||||
override Accessor getReadTarget() {
|
||||
this instanceof AssignableRead and result = this.getProperty().getReadTarget()
|
||||
this instanceof AssignableRead and result = this.getProperty().getGetter()
|
||||
}
|
||||
|
||||
override Accessor getWriteTarget() {
|
||||
this instanceof AssignableWrite and
|
||||
result = this.getProperty().getWriteTarget()
|
||||
exists(Property p | p = this.getProperty() |
|
||||
result = p.getSetter()
|
||||
or
|
||||
result =
|
||||
any(Getter g |
|
||||
g = p.getGetter() and
|
||||
g.getAnnotatedReturnType().isRef()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getArgument(int i) {
|
||||
@@ -798,12 +806,20 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
||||
*/
|
||||
class IndexerCall extends AccessorCall, IndexerAccessExpr {
|
||||
override Accessor getReadTarget() {
|
||||
this instanceof AssignableRead and result = this.getIndexer().getReadTarget()
|
||||
this instanceof AssignableRead and result = this.getIndexer().getGetter()
|
||||
}
|
||||
|
||||
override Accessor getWriteTarget() {
|
||||
this instanceof AssignableWrite and
|
||||
result = this.getIndexer().getWriteTarget()
|
||||
exists(Indexer i | i = this.getIndexer() |
|
||||
result = i.getSetter()
|
||||
or
|
||||
result =
|
||||
any(Getter g |
|
||||
g = i.getGetter() and
|
||||
g.getAnnotatedReturnType().isRef()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getArgument(int i) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import Creation
|
||||
import Dynamic
|
||||
import Literal
|
||||
import LogicalOperation
|
||||
import Operation
|
||||
import semmle.code.csharp.controlflow.ControlFlowElement
|
||||
import semmle.code.csharp.Location
|
||||
import semmle.code.csharp.Stmt
|
||||
@@ -211,7 +212,7 @@ class LocalConstantDeclExpr extends LocalVariableDeclExpr {
|
||||
* (`UnaryOperation`), a binary operation (`BinaryOperation`), or a
|
||||
* ternary operation (`TernaryOperation`).
|
||||
*/
|
||||
class Operation extends Expr, @operation_expr {
|
||||
class Operation extends Expr, @op_expr {
|
||||
/** Gets the name of the operator in this operation. */
|
||||
string getOperator() { none() }
|
||||
|
||||
@@ -226,7 +227,7 @@ class Operation extends Expr, @operation_expr {
|
||||
* indirection operation (`PointerIndirectionExpr`), an address-of operation
|
||||
* (`AddressOfExpr`), or a unary logical operation (`UnaryLogicalOperation`).
|
||||
*/
|
||||
class UnaryOperation extends Operation, @un_operation {
|
||||
class UnaryOperation extends Operation, @un_op {
|
||||
/** Gets the operand of this unary operation. */
|
||||
Expr getOperand() { result = this.getChild(0) }
|
||||
|
||||
@@ -240,7 +241,7 @@ class UnaryOperation extends Operation, @un_operation {
|
||||
* a binary logical operation (`BinaryLogicalOperation`), or an
|
||||
* assignment (`Assignment`).
|
||||
*/
|
||||
class BinaryOperation extends Operation, @bin_operation {
|
||||
class BinaryOperation extends Operation, @bin_op {
|
||||
/** Gets the left operand of this binary operation. */
|
||||
Expr getLeftOperand() { result = this.getChild(0) }
|
||||
|
||||
@@ -263,7 +264,7 @@ class BinaryOperation extends Operation, @bin_operation {
|
||||
* A ternary operation, that is, a ternary conditional operation
|
||||
* (`ConditionalExpr`).
|
||||
*/
|
||||
class TernaryOperation extends Operation, @ternary_operation { }
|
||||
class TernaryOperation extends Operation, @ternary_op { }
|
||||
|
||||
/**
|
||||
* A parenthesized expression, for example `(2 + 3)` in
|
||||
|
||||
@@ -11,14 +11,14 @@ import Expr
|
||||
* a binary logical operation (`BinaryLogicalOperation`), or a ternary logical
|
||||
* operation (`TernaryLogicalOperation`).
|
||||
*/
|
||||
class LogicalOperation extends Operation, @log_operation {
|
||||
class LogicalOperation extends Operation, @log_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`).
|
||||
*/
|
||||
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_operation { }
|
||||
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_op_expr { }
|
||||
|
||||
/**
|
||||
* A logical 'not', for example `!String.IsNullOrEmpty(s)`.
|
||||
@@ -31,10 +31,10 @@ class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr {
|
||||
|
||||
/**
|
||||
* A binary logical operation. Either a logical 'and' (`LogicalAndExpr`),
|
||||
* a logical 'or' (`LogicalOrExpr`), or a null-coalescing operation
|
||||
* (`NullCoalescingOperation`).
|
||||
* a logical 'or' (`LogicalAndExpr`), or a null-coalescing operation
|
||||
* (`NullCoalescingExpr`).
|
||||
*/
|
||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_operation {
|
||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
@@ -57,12 +57,7 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
|
||||
*/
|
||||
class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_operation { }
|
||||
|
||||
/**
|
||||
* A null-coalescing expression, for example `s ?? ""` on line 2 in
|
||||
* A null-coalescing operation, for example `s ?? ""` on line 2 in
|
||||
*
|
||||
* ```csharp
|
||||
* string NonNullOrEmpty(string s) {
|
||||
@@ -70,7 +65,9 @@ class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_o
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr {
|
||||
class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation,
|
||||
@null_coalescing_expr
|
||||
{
|
||||
override string getOperator() { result = "??" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
|
||||
@@ -80,7 +77,7 @@ class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr
|
||||
* A ternary logical operation, that is, a ternary conditional expression
|
||||
* (`ConditionalExpr`).
|
||||
*/
|
||||
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_operation { }
|
||||
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_op_expr { }
|
||||
|
||||
/**
|
||||
* A conditional expression, for example `s != null ? s.Length : -1`
|
||||
|
||||
@@ -1,6 +1,71 @@
|
||||
/**
|
||||
* Provides classes for operations that also have compound assignment forms.
|
||||
*/
|
||||
deprecated module;
|
||||
|
||||
import Expr
|
||||
|
||||
/**
|
||||
* An addition operation, either `x + y` or `x += y`.
|
||||
*/
|
||||
class AddOperation extends BinaryOperation, @add_operation { }
|
||||
|
||||
/**
|
||||
* A subtraction operation, either `x - y` or `x -= y`.
|
||||
*/
|
||||
class SubOperation extends BinaryOperation, @sub_operation { }
|
||||
|
||||
/**
|
||||
* A multiplication operation, either `x * y` or `x *= y`.
|
||||
*/
|
||||
class MulOperation extends BinaryOperation, @mul_operation { }
|
||||
|
||||
/**
|
||||
* A division operation, either `x / y` or `x /= y`.
|
||||
*/
|
||||
class DivOperation extends BinaryOperation, @div_operation {
|
||||
/** Gets the numerator of this division operation. */
|
||||
Expr getNumerator() { result = this.getLeftOperand() }
|
||||
|
||||
/** Gets the denominator of this division operation. */
|
||||
Expr getDenominator() { result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder operation, either `x % y` or `x %= y`.
|
||||
*/
|
||||
class RemOperation extends BinaryOperation, @rem_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise-and operation, either `x & y` or `x &= y`.
|
||||
*/
|
||||
class BitwiseAndOperation extends BinaryOperation, @and_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise-or operation, either `x | y` or `x |= y`.
|
||||
*/
|
||||
class BitwiseOrOperation extends BinaryOperation, @or_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
|
||||
*/
|
||||
class BitwiseXorOperation extends BinaryOperation, @xor_operation { }
|
||||
|
||||
/**
|
||||
* A left-shift operation, either `x << y` or `x <<= y`.
|
||||
*/
|
||||
class LeftShiftOperation extends BinaryOperation, @lshift_operation { }
|
||||
|
||||
/**
|
||||
* A right-shift operation, either `x >> y` or `x >>= y`.
|
||||
*/
|
||||
class RightShiftOperation extends BinaryOperation, @rshift_operation { }
|
||||
|
||||
/**
|
||||
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
|
||||
*/
|
||||
class UnsignedRightShiftOperation extends BinaryOperation, @urshift_operation { }
|
||||
|
||||
/**
|
||||
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
|
||||
*/
|
||||
class NullCoalescingOperation extends BinaryOperation, @null_coalescing_operation { }
|
||||
|
||||
@@ -13,7 +13,6 @@ private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.WCF
|
||||
private import semmle.code.csharp.frameworks.microsoft.Owin
|
||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
private import semmle.code.csharp.frameworks.Razor
|
||||
private import semmle.code.csharp.dataflow.internal.ExternalFlow
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
|
||||
|
||||
@@ -315,22 +314,6 @@ class AspNetCoreActionMethodParameter extends AspNetCoreRemoteFlowSource, DataFl
|
||||
override string getSourceType() { result = "ASP.NET Core MVC action method parameter" }
|
||||
}
|
||||
|
||||
/** A parameter to a Razor Page handler method, viewed as a source of remote user input. */
|
||||
class AspNetCorePageHandlerMethodParameter extends AspNetCoreRemoteFlowSource,
|
||||
DataFlow::ParameterNode
|
||||
{
|
||||
AspNetCorePageHandlerMethodParameter() {
|
||||
exists(Parameter p |
|
||||
p = this.getParameter() and
|
||||
p.fromSource()
|
||||
|
|
||||
p = any(PageModelClass pm).getAHandlerMethod().getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET Core Razor Page handler method parameter" }
|
||||
}
|
||||
|
||||
private class ExternalRemoteFlowSource extends RemoteFlowSource {
|
||||
ExternalRemoteFlowSource() { sourceNode(this, "remote") }
|
||||
|
||||
|
||||
@@ -1254,39 +1254,33 @@ case @expr.kind of
|
||||
|
||||
@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
|
||||
|
||||
@bin_arith_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
||||
@bin_arith_operation = @mul_operation | @div_operation | @rem_operation | @add_operation | @sub_operation;
|
||||
@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
||||
@incr_op_expr = @pre_incr_expr | @post_incr_expr;
|
||||
@decr_op_expr = @pre_decr_expr | @post_decr_expr;
|
||||
@mut_op_expr = @incr_op_expr | @decr_op_expr;
|
||||
@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
|
||||
@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
|
||||
|
||||
@incr_operation = @pre_incr_expr | @post_incr_expr;
|
||||
@decr_operation = @pre_decr_expr | @post_decr_expr;
|
||||
@mut_operation = @incr_operation | @decr_operation;
|
||||
@un_arith_operation = @plus_expr | @minus_expr | @mut_operation;
|
||||
@arith_operation = @bin_arith_operation | @un_arith_operation;
|
||||
@ternary_log_op_expr = @conditional_expr;
|
||||
@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
|
||||
@un_log_op_expr = @log_not_expr;
|
||||
@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
|
||||
|
||||
@ternary_log_operation = @conditional_expr;
|
||||
@bin_log_operation = @log_and_expr | @log_or_expr | @null_coalescing_operation;
|
||||
@un_log_operation = @log_not_expr;
|
||||
@log_operation = @un_log_operation | @bin_log_operation | @ternary_log_operation;
|
||||
|
||||
@bin_bit_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
|
||||
| @rshift_expr | @urshift_expr;
|
||||
@bin_bit_operation = @and_operation | @or_operation | @xor_operation | @lshift_operation
|
||||
| @rshift_operation | @urshift_operation;
|
||||
@un_bit_expr = @bit_not_expr;
|
||||
@un_bit_operation = @un_bit_expr;
|
||||
@bit_expr = @un_bit_expr | @bin_bit_expr;
|
||||
@bit_operation = @un_bit_operation | @bin_bit_operation;
|
||||
@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
|
||||
| @rshift_expr | @urshift_expr;
|
||||
@un_bit_op_expr = @bit_not_expr;
|
||||
@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
|
||||
|
||||
@equality_op_expr = @eq_expr | @ne_expr;
|
||||
@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
|
||||
@comp_expr = @equality_op_expr | @rel_op_expr;
|
||||
|
||||
@operation_expr = @un_operation | @bin_operation | @ternary_operation;
|
||||
@op_expr = @un_op | @bin_op | @ternary_op;
|
||||
|
||||
@ternary_operation = @ternary_log_operation;
|
||||
@bin_operation = @assign_expr | @bin_arith_operation | @bin_log_operation | @bin_bit_operation | @comp_expr;
|
||||
@un_operation = @un_arith_operation | @un_log_operation | @un_bit_operation | @sizeof_expr
|
||||
| @pointer_indirection_expr | @address_of_expr;
|
||||
@ternary_op = @ternary_log_op_expr;
|
||||
@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
|
||||
@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
|
||||
| @pointer_indirection_expr | @address_of_expr;
|
||||
|
||||
@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Restructure and rename types related to operations.
|
||||
compatibility: full
|
||||
@@ -63,7 +63,7 @@ module CallTargetStats implements StatsSig {
|
||||
|
||||
additional predicate isNotOkCall(Call c) {
|
||||
not exists(c.getTarget()) and
|
||||
not c instanceof DelegateLikeCall and
|
||||
not c instanceof DelegateCall and
|
||||
not c instanceof DynamicExpr and
|
||||
not isNoSetterPropertyCallInConstructor(c) and
|
||||
not isNoSetterPropertyInitialization(c) and
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
binarybitwise
|
||||
| Operators.cs:7:18:7:25 | ... >>> ... | Operators.cs:7:18:7:19 | access to local variable x1 | Operators.cs:7:25:7:25 | 2 | >>> | UnsignedRightShiftExpr |
|
||||
| Operators.cs:10:18:10:25 | ... >>> ... | Operators.cs:10:18:10:19 | access to local variable y1 | Operators.cs:10:25:10:25 | 3 | >>> | UnsignedRightShiftExpr |
|
||||
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
||||
assignbitwise
|
||||
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
||||
userdefined
|
||||
|
||||
@@ -11,7 +11,7 @@ query predicate binarybitwise(
|
||||
}
|
||||
|
||||
query predicate assignbitwise(
|
||||
AssignBitwiseExpr op, Expr left, Expr right, string name, string qlclass
|
||||
AssignBitwiseOperation op, Expr left, Expr right, string name, string qlclass
|
||||
) {
|
||||
op.getFile().getStem() = "Operators" and
|
||||
left = op.getLeftOperand() and
|
||||
|
||||
@@ -442,31 +442,4 @@ namespace My.Qltest
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
|
||||
// Test operator overloads
|
||||
public class N
|
||||
{
|
||||
public void operator +=(N y) => throw null;
|
||||
|
||||
public void operator checked +=(N y) => throw null;
|
||||
|
||||
public void M1(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
n += n0;
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
public void M2(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
checked
|
||||
{
|
||||
n += n0;
|
||||
}
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,16 +32,14 @@ models
|
||||
| 31 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
|
||||
| 32 | Summary: My.Qltest; Library; false; MixedFlowArgs; (System.Object,System.Object); ; Argument[1]; ReturnValue; value; manual |
|
||||
| 33 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
|
||||
| 34 | Summary: My.Qltest; N; false; op_AdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 35 | Summary: My.Qltest; N; false; op_CheckedAdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 42 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 43 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
| 34 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 35 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
edges
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
|
||||
@@ -164,77 +162,69 @@ edges
|
||||
| ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:373:23:373:34 | object creation of type Object : Object | ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | ExternalFlow.cs:375:18:375:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | ExternalFlow.cs:378:18:378:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:23:383:34 | object creation of type Object : Object | ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | ExternalFlow.cs:385:18:385:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | ExternalFlow.cs:388:18:388:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:393:23:393:34 | object creation of type Object : Object | ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | ExternalFlow.cs:396:18:396:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:401:23:401:34 | object creation of type Object : Object | ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | ExternalFlow.cs:404:18:404:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:23:409:34 | object creation of type Object : Object | ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | ExternalFlow.cs:411:18:411:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | ExternalFlow.cs:414:18:414:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | ExternalFlow.cs:421:18:421:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:40 |
|
||||
nodes
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
||||
@@ -453,16 +443,6 @@ nodes
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | semmle.label | call to extension accessor get_GenericProperty1 : Object |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | semmle.label | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | semmle.label | access to local variable o1 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
subpaths
|
||||
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
|
||||
invalidModelRow
|
||||
@@ -509,5 +489,3 @@ invalidModelRow
|
||||
| ExternalFlow.cs:424:18:424:19 | access to local variable o2 | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | $@ | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:432:18:432:19 | access to local variable o1 | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | $@ | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | $@ | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | $@ | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | object creation of type N : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | $@ | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | object creation of type N : N |
|
||||
|
||||
@@ -53,8 +53,6 @@ extensions:
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "GenericStaticMethod1", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "get_GenericProperty1", "(T)", "", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "set_GenericProperty1", "(T,T)", "", "Argument[1]", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "value", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_AdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_CheckedAdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
|
||||
@@ -63,32 +63,4 @@ namespace Testing
|
||||
{
|
||||
public void MyActionMethod(string param) { }
|
||||
}
|
||||
|
||||
// Razor Page handler tests
|
||||
public class MyPageModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
||||
{
|
||||
// Handler method parameters are remote flow sources
|
||||
public void OnGet(string id) { }
|
||||
|
||||
public void OnPost(string command, int count) { }
|
||||
|
||||
public void OnPostAsync(string data) { }
|
||||
|
||||
public void OnPut(string value) { }
|
||||
|
||||
public void OnDelete(string itemId) { }
|
||||
|
||||
// Not a handler method — does not start with "On", so not a flow source
|
||||
public void GetUser(string userId) { }
|
||||
|
||||
// Excluded by [NonHandler] attribute, so not a flow source
|
||||
[Microsoft.AspNetCore.Mvc.RazorPages.NonHandlerAttribute]
|
||||
public void OnGetNonHandler(string param) { }
|
||||
}
|
||||
|
||||
// Subclass of a PageModel subclass
|
||||
public class DerivedPageModel : MyPageModel
|
||||
{
|
||||
public void OnPost(string derivedParam) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,3 @@ remoteFlowSources
|
||||
| AspRemoteFlowSource.cs:54:69:54:82 | mapDeleteParam |
|
||||
| AspRemoteFlowSource.cs:56:41:56:44 | item |
|
||||
| AspRemoteFlowSource.cs:64:43:64:47 | param |
|
||||
| AspRemoteFlowSource.cs:71:34:71:35 | id |
|
||||
| AspRemoteFlowSource.cs:73:35:73:41 | command |
|
||||
| AspRemoteFlowSource.cs:73:48:73:52 | count |
|
||||
| AspRemoteFlowSource.cs:75:40:75:43 | data |
|
||||
| AspRemoteFlowSource.cs:77:34:77:38 | value |
|
||||
| AspRemoteFlowSource.cs:79:37:79:42 | itemId |
|
||||
| AspRemoteFlowSource.cs:92:35:92:46 | derivedParam |
|
||||
|
||||
@@ -293,69 +293,3 @@ properties.cs:
|
||||
# 160| 0: [LocalVariableAccess] access to local variable x
|
||||
# 160| 1: [PropertyCall] access to property Prop
|
||||
# 160| -1: [LocalVariableAccess] access to local variable s
|
||||
# 164| 13: [Class] BaseClass
|
||||
# 166| 6: [Property] Value
|
||||
# 166| -1: [TypeMention] int
|
||||
# 168| 3: [Getter] get_Value
|
||||
# 168| 4: [BlockStmt] {...}
|
||||
# 168| 0: [ReturnStmt] return ...;
|
||||
# 168| 0: [FieldAccess] access to field Value.field
|
||||
# 169| 4: [Setter] set_Value
|
||||
#-----| 2: (Parameters)
|
||||
# 169| 0: [Parameter] value
|
||||
# 169| 4: [BlockStmt] {...}
|
||||
# 169| 0: [ExprStmt] ...;
|
||||
# 169| 0: [AssignExpr] ... = ...
|
||||
# 169| 0: [FieldAccess] access to field Value.field
|
||||
# 169| 1: [ParameterAccess] access to parameter value
|
||||
# 166| 7: [Field] Value.field
|
||||
# 173| 14: [Class] DerivedClass1
|
||||
#-----| 3: (Base types)
|
||||
# 173| 0: [TypeMention] BaseClass
|
||||
# 175| 6: [Property] Value
|
||||
# 175| -1: [TypeMention] int
|
||||
# 177| 3: [Getter] get_Value
|
||||
# 177| 4: [BlockStmt] {...}
|
||||
# 177| 0: [ReturnStmt] return ...;
|
||||
# 177| 0: [IntLiteral] 20
|
||||
# 181| 15: [Class] DerivedClass2
|
||||
#-----| 3: (Base types)
|
||||
# 181| 0: [TypeMention] BaseClass
|
||||
# 183| 16: [Class] TestPartialPropertyOverride
|
||||
# 185| 6: [Method] M
|
||||
# 185| -1: [TypeMention] Void
|
||||
# 186| 4: [BlockStmt] {...}
|
||||
# 187| 0: [LocalVariableDeclStmt] ... ...;
|
||||
# 187| 0: [LocalVariableDeclAndInitExpr] DerivedClass1 d1 = ...
|
||||
# 187| -1: [TypeMention] DerivedClass1
|
||||
# 187| 0: [LocalVariableAccess] access to local variable d1
|
||||
# 187| 1: [ObjectCreation] object creation of type DerivedClass1
|
||||
# 187| 0: [TypeMention] DerivedClass1
|
||||
# 188| 1: [ExprStmt] ...;
|
||||
# 188| 0: [AssignExpr] ... = ...
|
||||
# 188| 0: [PropertyCall] access to property Value
|
||||
# 188| -1: [LocalVariableAccess] access to local variable d1
|
||||
# 188| 1: [IntLiteral] 11
|
||||
# 189| 2: [LocalVariableDeclStmt] ... ...;
|
||||
# 189| 0: [LocalVariableDeclAndInitExpr] Int32 test1 = ...
|
||||
# 189| -1: [TypeMention] int
|
||||
# 189| 0: [LocalVariableAccess] access to local variable test1
|
||||
# 189| 1: [PropertyCall] access to property Value
|
||||
# 189| -1: [LocalVariableAccess] access to local variable d1
|
||||
# 191| 3: [LocalVariableDeclStmt] ... ...;
|
||||
# 191| 0: [LocalVariableDeclAndInitExpr] DerivedClass2 d2 = ...
|
||||
# 191| -1: [TypeMention] DerivedClass2
|
||||
# 191| 0: [LocalVariableAccess] access to local variable d2
|
||||
# 191| 1: [ObjectCreation] object creation of type DerivedClass2
|
||||
# 191| 0: [TypeMention] DerivedClass2
|
||||
# 192| 4: [ExprStmt] ...;
|
||||
# 192| 0: [AssignExpr] ... = ...
|
||||
# 192| 0: [PropertyCall] access to property Value
|
||||
# 192| -1: [LocalVariableAccess] access to local variable d2
|
||||
# 192| 1: [IntLiteral] 12
|
||||
# 193| 5: [LocalVariableDeclStmt] ... ...;
|
||||
# 193| 0: [LocalVariableDeclAndInitExpr] Int32 test2 = ...
|
||||
# 193| -1: [TypeMention] int
|
||||
# 193| 0: [LocalVariableAccess] access to local variable test2
|
||||
# 193| 1: [PropertyCall] access to property Value
|
||||
# 193| -1: [LocalVariableAccess] access to local variable d2
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
| Prop.field |
|
||||
| Value.field |
|
||||
| caption |
|
||||
| next |
|
||||
| x |
|
||||
|
||||
@@ -6,7 +6,3 @@
|
||||
| properties.cs:71:28:71:28 | Y | properties.cs:83:39:83:44 | access to property Y | properties.cs:74:13:74:15 | set_Y |
|
||||
| properties.cs:146:24:146:27 | Prop | properties.cs:159:13:159:18 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
||||
| properties.cs:146:24:146:27 | Prop | properties.cs:160:21:160:26 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
||||
| properties.cs:166:28:166:32 | Value | properties.cs:192:13:192:20 | access to property Value | properties.cs:169:13:169:15 | set_Value |
|
||||
| properties.cs:166:28:166:32 | Value | properties.cs:193:25:193:32 | access to property Value | properties.cs:168:13:168:15 | get_Value |
|
||||
| properties.cs:175:29:175:33 | Value | properties.cs:188:13:188:20 | access to property Value | properties.cs:169:13:169:15 | set_Value |
|
||||
| properties.cs:175:29:175:33 | Value | properties.cs:189:25:189:32 | access to property Value | properties.cs:177:13:177:15 | get_Value |
|
||||
|
||||
@@ -160,37 +160,4 @@ namespace Properties
|
||||
var x = s.Prop;
|
||||
}
|
||||
}
|
||||
|
||||
public class BaseClass
|
||||
{
|
||||
public virtual int Value
|
||||
{
|
||||
get { return field; }
|
||||
set { field = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass1 : BaseClass
|
||||
{
|
||||
public override int Value
|
||||
{
|
||||
get { return 20; }
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass2 : BaseClass { }
|
||||
|
||||
public class TestPartialPropertyOverride
|
||||
{
|
||||
public void M()
|
||||
{
|
||||
var d1 = new DerivedClass1();
|
||||
d1.Value = 11;
|
||||
var test1 = d1.Value;
|
||||
|
||||
var d2 = new DerivedClass2();
|
||||
d2.Value = 12;
|
||||
var test2 = d2.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
|
||||
public class C
|
||||
{
|
||||
public void M(int a, int b)
|
||||
{
|
||||
var s = "hello world";
|
||||
var sub1 = s[1..a];
|
||||
var sub2 = s[..2];
|
||||
var sub3 = s[3..];
|
||||
var sub4 = s[..^4];
|
||||
var sub5 = s[a..^b];
|
||||
var sub6 = s[..];
|
||||
|
||||
Range range = 1..a;
|
||||
var sub7 = s[range];
|
||||
|
||||
Span<int> sp = null;
|
||||
var slice1 = sp[5..a];
|
||||
var slice2 = sp[..6];
|
||||
var slice3 = sp[7..];
|
||||
var slice4 = sp[..^8];
|
||||
var slice5 = sp[a..^b];
|
||||
var slice6 = sp[..];
|
||||
|
||||
Range range2 = 1..a;
|
||||
var slice7 = sp[range2];
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
methodArguments
|
||||
| Slice.cs:8:20:8:26 | call to method Substring | Substring(int, int) | 0 | 1 |
|
||||
| Slice.cs:8:20:8:26 | call to method Substring | Substring(int, int) | 1 | access to parameter a |
|
||||
| Slice.cs:9:20:9:25 | call to method Substring | Substring(int, int) | 0 | 0 |
|
||||
| Slice.cs:9:20:9:25 | call to method Substring | Substring(int, int) | 1 | 2 |
|
||||
| Slice.cs:10:20:10:25 | call to method Substring | Substring(int, int) | 0 | 3 |
|
||||
| Slice.cs:10:20:10:25 | call to method Substring | Substring(int, int) | 1 | ^0 |
|
||||
| Slice.cs:11:20:11:26 | call to method Substring | Substring(int, int) | 0 | 0 |
|
||||
| Slice.cs:11:20:11:26 | call to method Substring | Substring(int, int) | 1 | ^4 |
|
||||
| Slice.cs:12:20:12:27 | call to method Substring | Substring(int, int) | 0 | access to parameter a |
|
||||
| Slice.cs:12:20:12:27 | call to method Substring | Substring(int, int) | 1 | ^access to parameter b |
|
||||
| Slice.cs:13:20:13:24 | call to method Substring | Substring(int, int) | 0 | 0 |
|
||||
| Slice.cs:13:20:13:24 | call to method Substring | Substring(int, int) | 1 | ^0 |
|
||||
| Slice.cs:19:22:19:29 | call to method Slice | Slice(int, int) | 0 | 5 |
|
||||
| Slice.cs:19:22:19:29 | call to method Slice | Slice(int, int) | 1 | access to parameter a |
|
||||
| Slice.cs:20:22:20:28 | call to method Slice | Slice(int, int) | 0 | 0 |
|
||||
| Slice.cs:20:22:20:28 | call to method Slice | Slice(int, int) | 1 | 6 |
|
||||
| Slice.cs:21:22:21:28 | call to method Slice | Slice(int, int) | 0 | 7 |
|
||||
| Slice.cs:21:22:21:28 | call to method Slice | Slice(int, int) | 1 | ^0 |
|
||||
| Slice.cs:22:22:22:29 | call to method Slice | Slice(int, int) | 0 | 0 |
|
||||
| Slice.cs:22:22:22:29 | call to method Slice | Slice(int, int) | 1 | ^8 |
|
||||
| Slice.cs:23:22:23:30 | call to method Slice | Slice(int, int) | 0 | access to parameter a |
|
||||
| Slice.cs:23:22:23:30 | call to method Slice | Slice(int, int) | 1 | ^access to parameter b |
|
||||
| Slice.cs:24:22:24:27 | call to method Slice | Slice(int, int) | 0 | 0 |
|
||||
| Slice.cs:24:22:24:27 | call to method Slice | Slice(int, int) | 1 | ^0 |
|
||||
methodCalls
|
||||
| Slice.cs:3:14:3:14 | call to method <object initializer> | <object initializer>() |
|
||||
| Slice.cs:8:20:8:26 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:9:20:9:25 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:10:20:10:25 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:11:20:11:26 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:12:20:12:27 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:13:20:13:24 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:16:20:16:27 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:19:22:19:29 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:20:22:20:28 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:21:22:21:28 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:22:22:22:29 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:23:22:23:30 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:24:22:24:27 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:27:22:27:31 | call to method Slice | Slice(int, int) |
|
||||
@@ -1,17 +0,0 @@
|
||||
import csharp
|
||||
|
||||
private string printExpr(Expr e) {
|
||||
e = any(IndexExpr index | result = "^" + index.getExpr().toString())
|
||||
or
|
||||
not e instanceof IndexExpr and
|
||||
result = e.toString()
|
||||
}
|
||||
|
||||
query predicate methodArguments(MethodCall mc, string target, int i, string arg) {
|
||||
target = mc.getTarget().toStringWithTypes() and
|
||||
arg = printExpr(mc.getArgument(i))
|
||||
}
|
||||
|
||||
query predicate methodCalls(MethodCall mc, string target) {
|
||||
target = mc.getTarget().toStringWithTypes()
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
|
||||
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
|
||||
|
||||
@@ -7,5 +7,7 @@
|
||||
| Quality.cs:20:13:20:23 | access to property MyProperty6 | Call without target $@. | Quality.cs:20:13:20:23 | access to property MyProperty6 | access to property MyProperty6 |
|
||||
| Quality.cs:23:9:23:14 | access to event Event1 | Call without target $@. | Quality.cs:23:9:23:14 | access to event Event1 | access to event Event1 |
|
||||
| Quality.cs:23:9:23:30 | delegate call | Call without target $@. | Quality.cs:23:9:23:30 | delegate call | delegate call |
|
||||
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
|
||||
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
|
||||
| Quality.cs:38:16:38:26 | access to property MyProperty2 | Call without target $@. | Quality.cs:38:16:38:26 | access to property MyProperty2 | access to property MyProperty2 |
|
||||
| Quality.cs:50:20:50:26 | object creation of type T | Call without target $@. | Quality.cs:50:20:50:26 | object creation of type T | object creation of type T |
|
||||
|
||||
@@ -23,10 +23,10 @@ public class Test
|
||||
Event1.Invoke(this, 5);
|
||||
|
||||
var str = "abcd";
|
||||
var sub = str[..3];
|
||||
var sub = str[..3]; // TODO: this is not an indexer call, but rather a `str.Substring(0, 3)` call.
|
||||
|
||||
Span<int> sp = null;
|
||||
var slice = sp[..3];
|
||||
var slice = sp[..3]; // TODO: this is not an indexer call, but rather a `sp.Slice(0, 3)` call.
|
||||
|
||||
Span<byte> guidBytes = stackalloc byte[16];
|
||||
guidBytes[08] = 1;
|
||||
|
||||
@@ -10,7 +10,7 @@ toolchain go1.26.4
|
||||
// bazel mod tidy
|
||||
require (
|
||||
golang.org/x/mod v0.37.0
|
||||
golang.org/x/tools v0.46.0
|
||||
golang.org/x/tools v0.45.0
|
||||
)
|
||||
|
||||
require github.com/stretchr/testify v1.11.1
|
||||
@@ -18,6 +18,6 @@ require github.com/stretchr/testify v1.11.1
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -8,10 +8,10 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk=
|
||||
golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added models for the `log/slog` package (Go 1.21+). Its logging functions and
|
||||
`*slog.Logger` methods (`Debug`/`Info`/`Warn`/`Error`, their `Context`
|
||||
variants, and `Log`/`LogAttrs`) are now recognized as logging sinks, so the
|
||||
`go/log-injection` and `go/clear-text-logging` queries cover code that logs
|
||||
through `slog`.
|
||||
@@ -1,29 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/go-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
# Package-level convenience functions (msg string, args ...any).
|
||||
- ["log/slog", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
# Context variants (ctx, msg string, args ...any).
|
||||
- ["log/slog", "", False, "DebugContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "InfoContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "WarnContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "ErrorContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
# Log/LogAttrs (ctx, level, msg string, args/attrs ...).
|
||||
- ["log/slog", "", False, "Log", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "LogAttrs", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
# Methods on *slog.Logger.
|
||||
- ["log/slog", "Logger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "DebugContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "InfoContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "WarnContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "ErrorContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Log", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "LogAttrs", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
@@ -1049,29 +1049,17 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
|
||||
*/
|
||||
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th result declaration of this function type (0-based).
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl`.
|
||||
*/
|
||||
/** Gets the `i`th result of this function type (0-based). */
|
||||
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
|
||||
|
||||
/**
|
||||
* Gets a result declaration of this function type.
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl`.
|
||||
*/
|
||||
/** Gets a result of this function type. */
|
||||
ResultVariableDecl getAResultDecl() { result = this.getResultDecl(_) }
|
||||
|
||||
/** Gets the number of result parameters of this function type. */
|
||||
int getNumResult() { result = count(this.getAResultDecl().getANameExpr()) }
|
||||
/** Gets the number of results of this function type. */
|
||||
int getNumResult() { result = count(this.getAResultDecl()) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getResultDecl(int i)` instead.
|
||||
*/
|
||||
deprecated ResultVariableDecl getResultDecl() {
|
||||
this.getNumResult() = 1 and result = this.getAResultDecl()
|
||||
}
|
||||
/** Gets the result of this function type, if there is only one. */
|
||||
ResultVariableDecl getResultDecl() { this.getNumResult() = 1 and result = this.getAResultDecl() }
|
||||
|
||||
override string toString() { result = "function type" }
|
||||
|
||||
|
||||
@@ -923,20 +923,15 @@ module Public {
|
||||
/**
|
||||
* A node whose value is returned as a result from a function.
|
||||
*
|
||||
* If the function declares named result variables, this is a node representing
|
||||
* the current value of one of those variables at function exit. Otherwise, this
|
||||
* is a node corresponding to an expression in a return statement.
|
||||
* This can either be a node corresponding to an expression in a return statement,
|
||||
* or a node representing the current value of a named result variable at the exit
|
||||
* of the function.
|
||||
*/
|
||||
class ResultNode extends InstructionNode {
|
||||
int i;
|
||||
|
||||
ResultNode() {
|
||||
exists(FuncDef fd |
|
||||
// If the function has named result variables, then the
|
||||
// `IR::ReadResultInstruction` nodes at the end of the function are
|
||||
// the correct result nodes. Otherwise, the returned expressions are
|
||||
// the result nodes.
|
||||
not exists(fd.getAResultVar()) and
|
||||
exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i))
|
||||
or
|
||||
insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i))
|
||||
|
||||
@@ -55,7 +55,7 @@ class SyncFileFun extends Method {
|
||||
|
||||
/**
|
||||
* Holds if a `call` to a function is "unhandled". That is, it is either
|
||||
* deferred or used as an expression statement, so that its result is discarded.
|
||||
* deferred or its result is not assigned to anything.
|
||||
*
|
||||
* TODO: maybe we should check that something is actually done with the result
|
||||
*/
|
||||
@@ -77,6 +77,7 @@ predicate isWritableFileHandle(DataFlow::Node source, DataFlow::CallNode call) {
|
||||
// get the flags expression used for opening the file
|
||||
call.getArgument(1) = flags and
|
||||
// extract individual flags from the argument
|
||||
// flag = flag.getAChild*() and
|
||||
flag = getConstants(flags.asExpr()) and
|
||||
// check for one which signals that the handle will be writable
|
||||
// note that we are underestimating here, since the flags may be
|
||||
@@ -86,18 +87,27 @@ predicate isWritableFileHandle(DataFlow::Node source, DataFlow::CallNode call) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` post-dominates `node` in the control-flow graph. That is,
|
||||
* every path from `node` to the exit of the enclosing function passes through
|
||||
* `postDominator`.
|
||||
* Holds if `os.File.Close` is called on `sink`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate postDominatesNode(ControlFlow::Node postDominator, ControlFlow::Node node) {
|
||||
exists(ReachableBasicBlock pdbb, ReachableBasicBlock nbb, int i, int j |
|
||||
postDominator = pdbb.getNode(i) and node = nbb.getNode(j)
|
||||
|
|
||||
pdbb.strictlyPostDominates(nbb)
|
||||
or
|
||||
pdbb = nbb and i >= j
|
||||
predicate isCloseSink(DataFlow::Node sink, DataFlow::CallNode closeCall) {
|
||||
// find calls to the os.File.Close function
|
||||
closeCall = any(CloseFileFun f).getACall() and
|
||||
// that are unhandled
|
||||
unhandledCall(closeCall) and
|
||||
// where the function is called on the sink
|
||||
closeCall.getReceiver() = sink and
|
||||
// and check that it is not dominated by a call to `os.File.Sync`.
|
||||
// TODO: fix this logic when `closeCall` is in a defer statement.
|
||||
not exists(IR::Instruction syncInstr, DataFlow::Node syncReceiver, DataFlow::CallNode syncCall |
|
||||
// match the instruction corresponding to an `os.File.Sync` call with the predecessor
|
||||
syncCall.asInstruction() = syncInstr and
|
||||
// check that the call to `os.File.Sync` is handled
|
||||
isHandledSync(syncReceiver, syncCall) and
|
||||
// find a predecessor to `closeCall` in the control flow graph which dominates the call to
|
||||
// `os.File.Close`
|
||||
syncInstr.dominatesNode(closeCall.asInstruction()) and
|
||||
// check that `os.File.Sync` is called on the same object as `os.File.Close`
|
||||
exists(DataFlow::SsaNode ssa | ssa.getAUse() = sink and ssa.getAUse() = syncReceiver)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -117,39 +127,7 @@ predicate isHandledSync(DataFlow::Node sink, DataFlow::CallNode syncCall) {
|
||||
module UnhandledFileCloseConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isWritableFileHandle(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlow::CallNode closeCall |
|
||||
// `closeCall` is an unhandled call to `os.File.Close` on `sink`
|
||||
closeCall = any(CloseFileFun f).getACall() and
|
||||
unhandledCall(closeCall) and
|
||||
closeCall.getReceiver() = sink
|
||||
|
|
||||
// `closeCall` is not guaranteed to be preceded during
|
||||
// execution by a handled call to `os.File.Sync` on the same file handle.
|
||||
not exists(DataFlow::Node syncReceiver, DataFlow::CallNode syncCall |
|
||||
// check that the call to `os.File.Sync` is handled
|
||||
isHandledSync(syncReceiver, syncCall) and
|
||||
// check that `os.File.Sync` is called on the same object as `os.File.Close`
|
||||
exists(DataFlow::SsaNode ssa | ssa.getAUse() = sink and ssa.getAUse() = syncReceiver)
|
||||
|
|
||||
if exists(DeferStmt defer | defer.getCall() = closeCall.asExpr())
|
||||
then
|
||||
// When the call to `os.File.Close` is deferred it runs when the enclosing function
|
||||
// returns, but the receiver of the deferred call is evaluated where the `defer`
|
||||
// statement appears. It is therefore enough for the handled call to `os.File.Sync`
|
||||
// to post-dominate that point, since that guarantees `os.File.Sync` runs before the
|
||||
// deferred `os.File.Close` on every path on which the `os.File.Close` is registered.
|
||||
// We cannot reuse the domination check below because the control-flow graph splices
|
||||
// the deferred call in at the function exit, where it may be reachable along paths
|
||||
// that do not pass through the call to `os.File.Sync`.
|
||||
postDominatesNode(syncCall.asInstruction(), sink.asInstruction())
|
||||
else
|
||||
// Otherwise the call to `os.File.Close` is executed where it appears, so we require
|
||||
// the handled call to `os.File.Sync` to dominate it.
|
||||
syncCall.asInstruction().dominatesNode(closeCall.asInstruction())
|
||||
)
|
||||
)
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { isCloseSink(sink, _) }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
@@ -170,12 +148,14 @@ import UnhandledFileCloseFlow::PathGraph
|
||||
|
||||
from
|
||||
UnhandledFileCloseFlow::PathNode source, DataFlow::CallNode openCall,
|
||||
UnhandledFileCloseFlow::PathNode sink
|
||||
UnhandledFileCloseFlow::PathNode sink, DataFlow::CallNode closeCall
|
||||
where
|
||||
// find data flow from an `os.OpenFile` call to an `os.File.Close` call
|
||||
// where the handle is writable
|
||||
UnhandledFileCloseFlow::flowPath(source, sink) and
|
||||
isWritableFileHandle(source.getNode(), openCall)
|
||||
isWritableFileHandle(source.getNode(), openCall) and
|
||||
// get the `CallNode` corresponding to the sink
|
||||
isCloseSink(sink.getNode(), closeCall)
|
||||
select sink, source, sink,
|
||||
"File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly.",
|
||||
openCall, openCall.toString()
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The query `go/unhandled-writable-file-close` ("Writable file handle closed without error handling") now produces fewer false positives. A deferred call to `Close` that is preceded on every execution path by a handled call to `Sync` on the same file handle is no longer flagged.
|
||||
@@ -1,6 +1,6 @@
|
||||
module codeql-go-tests/concepts/loggercall
|
||||
|
||||
go 1.21
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/golang/glog v1.2.5
|
||||
|
||||
@@ -2,12 +2,10 @@ package main
|
||||
|
||||
const fmt = "formatted %s string"
|
||||
const text = "test"
|
||||
const key = "key"
|
||||
|
||||
var v []byte
|
||||
|
||||
func main() {
|
||||
glogTest(len(v))
|
||||
stdlib()
|
||||
slogTest()
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func slogTest() {
|
||||
ctx := context.Background()
|
||||
var logger *slog.Logger
|
||||
var attr slog.Attr
|
||||
|
||||
// Methods on *slog.Logger: Debug/Info/Warn/Error(msg string, args ...any).
|
||||
logger.Debug(text) // $ logger=text
|
||||
logger.Info(text) // $ logger=text
|
||||
logger.Warn(text) // $ logger=text
|
||||
logger.Error(text) // $ logger=text
|
||||
logger.Info(text, key, v) // $ logger=text logger=key logger=v
|
||||
|
||||
// Context variants: (ctx, msg string, args ...any).
|
||||
logger.DebugContext(ctx, text) // $ logger=text
|
||||
logger.InfoContext(ctx, text) // $ logger=text
|
||||
logger.WarnContext(ctx, text) // $ logger=text
|
||||
logger.ErrorContext(ctx, text) // $ logger=text
|
||||
logger.InfoContext(ctx, text, key, v) // $ logger=text logger=key logger=v
|
||||
|
||||
// Log/LogAttrs: (ctx, level, msg string, args/attrs ...).
|
||||
logger.Log(ctx, slog.LevelInfo, text, key, v) // $ logger=text logger=key logger=v
|
||||
logger.LogAttrs(ctx, slog.LevelInfo, text, attr) // $ logger=text logger=attr
|
||||
|
||||
// Package-level convenience functions.
|
||||
slog.Debug(text) // $ logger=text
|
||||
slog.Info(text) // $ logger=text
|
||||
slog.Warn(text) // $ logger=text
|
||||
slog.Error(text) // $ logger=text
|
||||
slog.Info(text, key, v) // $ logger=text logger=key logger=v
|
||||
slog.InfoContext(ctx, text, key, v) // $ logger=text logger=key logger=v
|
||||
slog.Log(ctx, slog.LevelInfo, text, key, v) // $ logger=text logger=key logger=v
|
||||
slog.LogAttrs(ctx, slog.LevelInfo, text, attr) // $ logger=text logger=attr
|
||||
}
|
||||
@@ -735,153 +735,129 @@
|
||||
| main.go:48:11:48:12 | 42 | main.go:48:2:48:7 | assignment to result |
|
||||
| main.go:49:2:49:7 | return statement | main.go:47:13:47:18 | implicit read of result |
|
||||
| main.go:52:1:54:1 | entry | main.go:52:14:52:19 | zero value for result |
|
||||
| main.go:52:1:54:1 | function declaration | main.go:56:6:56:9 | skip |
|
||||
| main.go:52:1:54:1 | function declaration | main.go:56:6:56:10 | skip |
|
||||
| main.go:52:6:52:9 | skip | main.go:52:1:54:1 | function declaration |
|
||||
| main.go:52:14:52:19 | implicit read of result | main.go:52:1:54:1 | exit |
|
||||
| main.go:52:14:52:19 | initialization of result | main.go:53:2:53:7 | return statement |
|
||||
| main.go:52:14:52:19 | zero value for result | main.go:52:14:52:19 | initialization of result |
|
||||
| main.go:53:2:53:7 | return statement | main.go:52:14:52:19 | implicit read of result |
|
||||
| main.go:56:1:64:1 | entry | main.go:56:11:56:18 | argument corresponding to selector |
|
||||
| main.go:56:1:64:1 | function declaration | main.go:66:6:66:10 | skip |
|
||||
| main.go:56:6:56:9 | skip | main.go:56:1:64:1 | function declaration |
|
||||
| main.go:56:11:56:18 | argument corresponding to selector | main.go:56:11:56:18 | initialization of selector |
|
||||
| main.go:56:11:56:18 | initialization of selector | main.go:56:26:56:31 | zero value for result |
|
||||
| main.go:56:26:56:31 | implicit read of result | main.go:56:1:64:1 | exit |
|
||||
| main.go:56:26:56:31 | initialization of result | main.go:57:2:57:7 | skip |
|
||||
| main.go:56:26:56:31 | zero value for result | main.go:56:26:56:31 | initialization of result |
|
||||
| main.go:57:2:57:7 | assignment to result | main.go:58:5:58:12 | selector |
|
||||
| main.go:57:2:57:7 | skip | main.go:57:11:57:11 | 0 |
|
||||
| main.go:57:11:57:11 | 0 | main.go:57:2:57:7 | assignment to result |
|
||||
| main.go:58:5:58:12 | selector | main.go:58:17:58:17 | 1 |
|
||||
| main.go:58:5:58:17 | ...==... | main.go:58:5:58:17 | ...==... is false |
|
||||
| main.go:58:5:58:17 | ...==... | main.go:58:5:58:17 | ...==... is true |
|
||||
| main.go:58:5:58:17 | ...==... is false | main.go:61:3:61:8 | skip |
|
||||
| main.go:58:5:58:17 | ...==... is true | main.go:59:10:59:10 | 1 |
|
||||
| main.go:58:17:58:17 | 1 | main.go:58:5:58:17 | ...==... |
|
||||
| main.go:59:3:59:10 | return statement | main.go:56:26:56:31 | implicit read of result |
|
||||
| main.go:59:10:59:10 | 1 | main.go:59:10:59:10 | implicit write of result |
|
||||
| main.go:59:10:59:10 | implicit write of result | main.go:59:3:59:10 | return statement |
|
||||
| main.go:61:3:61:8 | assignment to result | main.go:63:2:63:7 | return statement |
|
||||
| main.go:61:3:61:8 | skip | main.go:61:12:61:12 | 2 |
|
||||
| main.go:61:12:61:12 | 2 | main.go:61:3:61:8 | assignment to result |
|
||||
| main.go:63:2:63:7 | return statement | main.go:56:26:56:31 | implicit read of result |
|
||||
| main.go:66:1:90:1 | entry | main.go:67:6:67:6 | skip |
|
||||
| main.go:66:1:90:1 | function declaration | main.go:92:6:92:13 | skip |
|
||||
| main.go:66:6:66:10 | skip | main.go:66:1:90:1 | function declaration |
|
||||
| main.go:67:6:67:6 | assignment to x | main.go:68:6:68:9 | cond |
|
||||
| main.go:67:6:67:6 | skip | main.go:67:6:67:6 | zero value for x |
|
||||
| main.go:67:6:67:6 | zero value for x | main.go:67:6:67:6 | assignment to x |
|
||||
| main.go:68:6:68:9 | cond | main.go:68:6:68:11 | call to cond |
|
||||
| main.go:68:6:68:11 | call to cond | main.go:66:1:90:1 | exit |
|
||||
| main.go:68:6:68:11 | call to cond | main.go:68:6:68:11 | call to cond is false |
|
||||
| main.go:68:6:68:11 | call to cond | main.go:68:6:68:11 | call to cond is true |
|
||||
| main.go:68:6:68:11 | call to cond is false | main.go:71:2:71:10 | selection of Print |
|
||||
| main.go:68:6:68:11 | call to cond is true | main.go:69:3:69:3 | skip |
|
||||
| main.go:69:3:69:3 | assignment to x | main.go:68:6:68:9 | cond |
|
||||
| main.go:69:3:69:3 | skip | main.go:69:7:69:7 | 2 |
|
||||
| main.go:69:7:69:7 | 2 | main.go:69:3:69:3 | assignment to x |
|
||||
| main.go:71:2:71:10 | selection of Print | main.go:71:12:71:12 | x |
|
||||
| main.go:71:2:71:13 | call to Print | main.go:66:1:90:1 | exit |
|
||||
| main.go:71:2:71:13 | call to Print | main.go:73:2:73:2 | skip |
|
||||
| main.go:71:12:71:12 | x | main.go:71:2:71:13 | call to Print |
|
||||
| main.go:73:2:73:2 | assignment to y | main.go:74:6:74:6 | skip |
|
||||
| main.go:73:2:73:2 | skip | main.go:73:7:73:7 | 1 |
|
||||
| main.go:73:7:73:7 | 1 | main.go:73:2:73:2 | assignment to y |
|
||||
| main.go:74:6:74:6 | assignment to i | main.go:75:6:75:9 | cond |
|
||||
| main.go:74:6:74:6 | skip | main.go:74:11:74:11 | 0 |
|
||||
| main.go:74:11:74:11 | 0 | main.go:74:6:74:6 | assignment to i |
|
||||
| main.go:74:16:74:16 | i | main.go:74:16:74:18 | 1 |
|
||||
| main.go:74:16:74:18 | 1 | main.go:74:16:74:18 | rhs of increment statement |
|
||||
| main.go:74:16:74:18 | increment statement | main.go:75:6:75:9 | cond |
|
||||
| main.go:74:16:74:18 | rhs of increment statement | main.go:74:16:74:18 | increment statement |
|
||||
| main.go:56:1:80:1 | entry | main.go:57:6:57:6 | skip |
|
||||
| main.go:56:1:80:1 | function declaration | main.go:82:6:82:13 | skip |
|
||||
| main.go:56:6:56:10 | skip | main.go:56:1:80:1 | function declaration |
|
||||
| main.go:57:6:57:6 | assignment to x | main.go:58:6:58:9 | cond |
|
||||
| main.go:57:6:57:6 | skip | main.go:57:6:57:6 | zero value for x |
|
||||
| main.go:57:6:57:6 | zero value for x | main.go:57:6:57:6 | assignment to x |
|
||||
| main.go:58:6:58:9 | cond | main.go:58:6:58:11 | call to cond |
|
||||
| main.go:58:6:58:11 | call to cond | main.go:56:1:80:1 | exit |
|
||||
| main.go:58:6:58:11 | call to cond | main.go:58:6:58:11 | call to cond is false |
|
||||
| main.go:58:6:58:11 | call to cond | main.go:58:6:58:11 | call to cond is true |
|
||||
| main.go:58:6:58:11 | call to cond is false | main.go:61:2:61:10 | selection of Print |
|
||||
| main.go:58:6:58:11 | call to cond is true | main.go:59:3:59:3 | skip |
|
||||
| main.go:59:3:59:3 | assignment to x | main.go:58:6:58:9 | cond |
|
||||
| main.go:59:3:59:3 | skip | main.go:59:7:59:7 | 2 |
|
||||
| main.go:59:7:59:7 | 2 | main.go:59:3:59:3 | assignment to x |
|
||||
| main.go:61:2:61:10 | selection of Print | main.go:61:12:61:12 | x |
|
||||
| main.go:61:2:61:13 | call to Print | main.go:56:1:80:1 | exit |
|
||||
| main.go:61:2:61:13 | call to Print | main.go:63:2:63:2 | skip |
|
||||
| main.go:61:12:61:12 | x | main.go:61:2:61:13 | call to Print |
|
||||
| main.go:63:2:63:2 | assignment to y | main.go:64:6:64:6 | skip |
|
||||
| main.go:63:2:63:2 | skip | main.go:63:7:63:7 | 1 |
|
||||
| main.go:63:7:63:7 | 1 | main.go:63:2:63:2 | assignment to y |
|
||||
| main.go:64:6:64:6 | assignment to i | main.go:65:6:65:9 | cond |
|
||||
| main.go:64:6:64:6 | skip | main.go:64:11:64:11 | 0 |
|
||||
| main.go:64:11:64:11 | 0 | main.go:64:6:64:6 | assignment to i |
|
||||
| main.go:64:16:64:16 | i | main.go:64:16:64:18 | 1 |
|
||||
| main.go:64:16:64:18 | 1 | main.go:64:16:64:18 | rhs of increment statement |
|
||||
| main.go:64:16:64:18 | increment statement | main.go:65:6:65:9 | cond |
|
||||
| main.go:64:16:64:18 | rhs of increment statement | main.go:64:16:64:18 | increment statement |
|
||||
| main.go:65:6:65:9 | cond | main.go:65:6:65:11 | call to cond |
|
||||
| main.go:65:6:65:11 | call to cond | main.go:56:1:80:1 | exit |
|
||||
| main.go:65:6:65:11 | call to cond | main.go:65:6:65:11 | call to cond is false |
|
||||
| main.go:65:6:65:11 | call to cond | main.go:65:6:65:11 | call to cond is true |
|
||||
| main.go:65:6:65:11 | call to cond is false | main.go:68:3:68:3 | skip |
|
||||
| main.go:65:6:65:11 | call to cond is true | main.go:66:4:66:8 | skip |
|
||||
| main.go:66:4:66:8 | skip | main.go:70:2:70:10 | selection of Print |
|
||||
| main.go:68:3:68:3 | assignment to y | main.go:64:16:64:16 | i |
|
||||
| main.go:68:3:68:3 | skip | main.go:68:7:68:7 | 2 |
|
||||
| main.go:68:7:68:7 | 2 | main.go:68:3:68:3 | assignment to y |
|
||||
| main.go:70:2:70:10 | selection of Print | main.go:70:12:70:12 | y |
|
||||
| main.go:70:2:70:13 | call to Print | main.go:56:1:80:1 | exit |
|
||||
| main.go:70:2:70:13 | call to Print | main.go:72:2:72:2 | skip |
|
||||
| main.go:70:12:70:12 | y | main.go:70:2:70:13 | call to Print |
|
||||
| main.go:72:2:72:2 | assignment to z | main.go:73:6:73:6 | skip |
|
||||
| main.go:72:2:72:2 | skip | main.go:72:7:72:7 | 1 |
|
||||
| main.go:72:7:72:7 | 1 | main.go:72:2:72:2 | assignment to z |
|
||||
| main.go:73:6:73:6 | assignment to i | main.go:74:3:74:3 | skip |
|
||||
| main.go:73:6:73:6 | skip | main.go:73:11:73:11 | 0 |
|
||||
| main.go:73:11:73:11 | 0 | main.go:73:6:73:6 | assignment to i |
|
||||
| main.go:73:16:73:16 | i | main.go:73:16:73:18 | 1 |
|
||||
| main.go:73:16:73:18 | 1 | main.go:73:16:73:18 | rhs of increment statement |
|
||||
| main.go:73:16:73:18 | increment statement | main.go:74:3:74:3 | skip |
|
||||
| main.go:73:16:73:18 | rhs of increment statement | main.go:73:16:73:18 | increment statement |
|
||||
| main.go:74:3:74:3 | assignment to z | main.go:75:6:75:9 | cond |
|
||||
| main.go:74:3:74:3 | skip | main.go:74:7:74:7 | 2 |
|
||||
| main.go:74:7:74:7 | 2 | main.go:74:3:74:3 | assignment to z |
|
||||
| main.go:75:6:75:9 | cond | main.go:75:6:75:11 | call to cond |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:66:1:90:1 | exit |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:56:1:80:1 | exit |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:75:6:75:11 | call to cond is false |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:75:6:75:11 | call to cond is true |
|
||||
| main.go:75:6:75:11 | call to cond is false | main.go:78:3:78:3 | skip |
|
||||
| main.go:75:6:75:11 | call to cond is false | main.go:73:16:73:16 | i |
|
||||
| main.go:75:6:75:11 | call to cond is true | main.go:76:4:76:8 | skip |
|
||||
| main.go:76:4:76:8 | skip | main.go:80:2:80:10 | selection of Print |
|
||||
| main.go:78:3:78:3 | assignment to y | main.go:74:16:74:16 | i |
|
||||
| main.go:78:3:78:3 | skip | main.go:78:7:78:7 | 2 |
|
||||
| main.go:78:7:78:7 | 2 | main.go:78:3:78:3 | assignment to y |
|
||||
| main.go:80:2:80:10 | selection of Print | main.go:80:12:80:12 | y |
|
||||
| main.go:80:2:80:13 | call to Print | main.go:66:1:90:1 | exit |
|
||||
| main.go:80:2:80:13 | call to Print | main.go:82:2:82:2 | skip |
|
||||
| main.go:80:12:80:12 | y | main.go:80:2:80:13 | call to Print |
|
||||
| main.go:82:2:82:2 | assignment to z | main.go:83:6:83:6 | skip |
|
||||
| main.go:82:2:82:2 | skip | main.go:82:7:82:7 | 1 |
|
||||
| main.go:82:7:82:7 | 1 | main.go:82:2:82:2 | assignment to z |
|
||||
| main.go:83:6:83:6 | assignment to i | main.go:84:3:84:3 | skip |
|
||||
| main.go:83:6:83:6 | skip | main.go:83:11:83:11 | 0 |
|
||||
| main.go:83:11:83:11 | 0 | main.go:83:6:83:6 | assignment to i |
|
||||
| main.go:83:16:83:16 | i | main.go:83:16:83:18 | 1 |
|
||||
| main.go:83:16:83:18 | 1 | main.go:83:16:83:18 | rhs of increment statement |
|
||||
| main.go:83:16:83:18 | increment statement | main.go:84:3:84:3 | skip |
|
||||
| main.go:83:16:83:18 | rhs of increment statement | main.go:83:16:83:18 | increment statement |
|
||||
| main.go:84:3:84:3 | assignment to z | main.go:85:6:85:9 | cond |
|
||||
| main.go:84:3:84:3 | skip | main.go:84:7:84:7 | 2 |
|
||||
| main.go:84:7:84:7 | 2 | main.go:84:3:84:3 | assignment to z |
|
||||
| main.go:85:6:85:9 | cond | main.go:85:6:85:11 | call to cond |
|
||||
| main.go:85:6:85:11 | call to cond | main.go:66:1:90:1 | exit |
|
||||
| main.go:85:6:85:11 | call to cond | main.go:85:6:85:11 | call to cond is false |
|
||||
| main.go:85:6:85:11 | call to cond | main.go:85:6:85:11 | call to cond is true |
|
||||
| main.go:85:6:85:11 | call to cond is false | main.go:83:16:83:16 | i |
|
||||
| main.go:85:6:85:11 | call to cond is true | main.go:86:4:86:8 | skip |
|
||||
| main.go:86:4:86:8 | skip | main.go:89:2:89:10 | selection of Print |
|
||||
| main.go:89:2:89:10 | selection of Print | main.go:89:12:89:12 | z |
|
||||
| main.go:89:2:89:13 | call to Print | main.go:66:1:90:1 | exit |
|
||||
| main.go:89:12:89:12 | z | main.go:89:2:89:13 | call to Print |
|
||||
| main.go:92:1:96:1 | entry | main.go:92:18:92:18 | zero value for a |
|
||||
| main.go:92:1:96:1 | function declaration | main.go:98:6:98:23 | skip |
|
||||
| main.go:92:6:92:13 | skip | main.go:92:1:96:1 | function declaration |
|
||||
| main.go:92:18:92:18 | implicit read of a | main.go:92:25:92:25 | implicit read of b |
|
||||
| main.go:92:18:92:18 | initialization of a | main.go:92:25:92:25 | zero value for b |
|
||||
| main.go:92:18:92:18 | zero value for a | main.go:92:18:92:18 | initialization of a |
|
||||
| main.go:92:25:92:25 | implicit read of b | main.go:92:1:96:1 | exit |
|
||||
| main.go:92:25:92:25 | initialization of b | main.go:93:2:93:2 | skip |
|
||||
| main.go:92:25:92:25 | zero value for b | main.go:92:25:92:25 | initialization of b |
|
||||
| main.go:93:2:93:2 | assignment to x | main.go:94:2:94:2 | skip |
|
||||
| main.go:93:2:93:2 | skip | main.go:93:7:93:8 | 23 |
|
||||
| main.go:93:7:93:8 | 23 | main.go:93:2:93:2 | assignment to x |
|
||||
| main.go:94:2:94:2 | assignment to x | main.go:94:5:94:5 | assignment to a |
|
||||
| main.go:94:2:94:2 | skip | main.go:94:5:94:5 | skip |
|
||||
| main.go:94:5:94:5 | assignment to a | main.go:95:2:95:7 | return statement |
|
||||
| main.go:94:5:94:5 | skip | main.go:94:9:94:9 | x |
|
||||
| main.go:94:9:94:9 | x | main.go:94:11:94:12 | 19 |
|
||||
| main.go:94:9:94:12 | ...+... | main.go:94:15:94:15 | x |
|
||||
| main.go:94:11:94:12 | 19 | main.go:94:9:94:12 | ...+... |
|
||||
| main.go:94:15:94:15 | x | main.go:94:2:94:2 | assignment to x |
|
||||
| main.go:95:2:95:7 | return statement | main.go:92:18:92:18 | implicit read of a |
|
||||
| main.go:98:1:106:1 | entry | main.go:98:25:98:25 | argument corresponding to x |
|
||||
| main.go:98:1:106:1 | function declaration | main.go:0:0:0:0 | exit |
|
||||
| main.go:98:6:98:23 | skip | main.go:98:1:106:1 | function declaration |
|
||||
| main.go:98:25:98:25 | argument corresponding to x | main.go:98:25:98:25 | initialization of x |
|
||||
| main.go:98:25:98:25 | initialization of x | main.go:99:2:99:2 | skip |
|
||||
| main.go:99:2:99:2 | assignment to a | main.go:99:5:99:5 | assignment to b |
|
||||
| main.go:99:2:99:2 | skip | main.go:99:5:99:5 | skip |
|
||||
| main.go:99:5:99:5 | assignment to b | main.go:100:5:100:8 | cond |
|
||||
| main.go:99:5:99:5 | skip | main.go:99:10:99:10 | x |
|
||||
| main.go:99:10:99:10 | x | main.go:99:13:99:13 | 0 |
|
||||
| main.go:99:13:99:13 | 0 | main.go:99:2:99:2 | assignment to a |
|
||||
| main.go:100:5:100:8 | cond | main.go:100:5:100:10 | call to cond |
|
||||
| main.go:100:5:100:10 | call to cond | main.go:98:1:106:1 | exit |
|
||||
| main.go:100:5:100:10 | call to cond | main.go:100:5:100:10 | call to cond is false |
|
||||
| main.go:100:5:100:10 | call to cond | main.go:100:5:100:10 | call to cond is true |
|
||||
| main.go:100:5:100:10 | call to cond is false | main.go:103:3:103:3 | skip |
|
||||
| main.go:100:5:100:10 | call to cond is true | main.go:101:3:101:3 | skip |
|
||||
| main.go:101:3:101:3 | assignment to a | main.go:105:9:105:9 | a |
|
||||
| main.go:101:3:101:3 | skip | main.go:101:6:101:6 | skip |
|
||||
| main.go:101:6:101:6 | skip | main.go:101:10:101:10 | b |
|
||||
| main.go:101:10:101:10 | b | main.go:101:13:101:13 | a |
|
||||
| main.go:101:13:101:13 | a | main.go:101:3:101:3 | assignment to a |
|
||||
| main.go:103:3:103:3 | skip | main.go:103:6:103:6 | skip |
|
||||
| main.go:103:6:103:6 | assignment to b | main.go:105:9:105:9 | a |
|
||||
| main.go:103:6:103:6 | skip | main.go:103:10:103:10 | b |
|
||||
| main.go:103:10:103:10 | b | main.go:103:13:103:13 | a |
|
||||
| main.go:103:13:103:13 | a | main.go:103:6:103:6 | assignment to b |
|
||||
| main.go:105:2:105:12 | return statement | main.go:98:1:106:1 | exit |
|
||||
| main.go:105:9:105:9 | a | main.go:105:12:105:12 | b |
|
||||
| main.go:105:12:105:12 | b | main.go:105:2:105:12 | return statement |
|
||||
| main.go:76:4:76:8 | skip | main.go:79:2:79:10 | selection of Print |
|
||||
| main.go:79:2:79:10 | selection of Print | main.go:79:12:79:12 | z |
|
||||
| main.go:79:2:79:13 | call to Print | main.go:56:1:80:1 | exit |
|
||||
| main.go:79:12:79:12 | z | main.go:79:2:79:13 | call to Print |
|
||||
| main.go:82:1:86:1 | entry | main.go:82:18:82:18 | zero value for a |
|
||||
| main.go:82:1:86:1 | function declaration | main.go:88:6:88:23 | skip |
|
||||
| main.go:82:6:82:13 | skip | main.go:82:1:86:1 | function declaration |
|
||||
| main.go:82:18:82:18 | implicit read of a | main.go:82:25:82:25 | implicit read of b |
|
||||
| main.go:82:18:82:18 | initialization of a | main.go:82:25:82:25 | zero value for b |
|
||||
| main.go:82:18:82:18 | zero value for a | main.go:82:18:82:18 | initialization of a |
|
||||
| main.go:82:25:82:25 | implicit read of b | main.go:82:1:86:1 | exit |
|
||||
| main.go:82:25:82:25 | initialization of b | main.go:83:2:83:2 | skip |
|
||||
| main.go:82:25:82:25 | zero value for b | main.go:82:25:82:25 | initialization of b |
|
||||
| main.go:83:2:83:2 | assignment to x | main.go:84:2:84:2 | skip |
|
||||
| main.go:83:2:83:2 | skip | main.go:83:7:83:8 | 23 |
|
||||
| main.go:83:7:83:8 | 23 | main.go:83:2:83:2 | assignment to x |
|
||||
| main.go:84:2:84:2 | assignment to x | main.go:84:5:84:5 | assignment to a |
|
||||
| main.go:84:2:84:2 | skip | main.go:84:5:84:5 | skip |
|
||||
| main.go:84:5:84:5 | assignment to a | main.go:85:2:85:7 | return statement |
|
||||
| main.go:84:5:84:5 | skip | main.go:84:9:84:9 | x |
|
||||
| main.go:84:9:84:9 | x | main.go:84:11:84:12 | 19 |
|
||||
| main.go:84:9:84:12 | ...+... | main.go:84:15:84:15 | x |
|
||||
| main.go:84:11:84:12 | 19 | main.go:84:9:84:12 | ...+... |
|
||||
| main.go:84:15:84:15 | x | main.go:84:2:84:2 | assignment to x |
|
||||
| main.go:85:2:85:7 | return statement | main.go:82:18:82:18 | implicit read of a |
|
||||
| main.go:88:1:96:1 | entry | main.go:88:25:88:25 | argument corresponding to x |
|
||||
| main.go:88:1:96:1 | function declaration | main.go:0:0:0:0 | exit |
|
||||
| main.go:88:6:88:23 | skip | main.go:88:1:96:1 | function declaration |
|
||||
| main.go:88:25:88:25 | argument corresponding to x | main.go:88:25:88:25 | initialization of x |
|
||||
| main.go:88:25:88:25 | initialization of x | main.go:89:2:89:2 | skip |
|
||||
| main.go:89:2:89:2 | assignment to a | main.go:89:5:89:5 | assignment to b |
|
||||
| main.go:89:2:89:2 | skip | main.go:89:5:89:5 | skip |
|
||||
| main.go:89:5:89:5 | assignment to b | main.go:90:5:90:8 | cond |
|
||||
| main.go:89:5:89:5 | skip | main.go:89:10:89:10 | x |
|
||||
| main.go:89:10:89:10 | x | main.go:89:13:89:13 | 0 |
|
||||
| main.go:89:13:89:13 | 0 | main.go:89:2:89:2 | assignment to a |
|
||||
| main.go:90:5:90:8 | cond | main.go:90:5:90:10 | call to cond |
|
||||
| main.go:90:5:90:10 | call to cond | main.go:88:1:96:1 | exit |
|
||||
| main.go:90:5:90:10 | call to cond | main.go:90:5:90:10 | call to cond is false |
|
||||
| main.go:90:5:90:10 | call to cond | main.go:90:5:90:10 | call to cond is true |
|
||||
| main.go:90:5:90:10 | call to cond is false | main.go:93:3:93:3 | skip |
|
||||
| main.go:90:5:90:10 | call to cond is true | main.go:91:3:91:3 | skip |
|
||||
| main.go:91:3:91:3 | assignment to a | main.go:95:9:95:9 | a |
|
||||
| main.go:91:3:91:3 | skip | main.go:91:6:91:6 | skip |
|
||||
| main.go:91:6:91:6 | skip | main.go:91:10:91:10 | b |
|
||||
| main.go:91:10:91:10 | b | main.go:91:13:91:13 | a |
|
||||
| main.go:91:13:91:13 | a | main.go:91:3:91:3 | assignment to a |
|
||||
| main.go:93:3:93:3 | skip | main.go:93:6:93:6 | skip |
|
||||
| main.go:93:6:93:6 | assignment to b | main.go:95:9:95:9 | a |
|
||||
| main.go:93:6:93:6 | skip | main.go:93:10:93:10 | b |
|
||||
| main.go:93:10:93:10 | b | main.go:93:13:93:13 | a |
|
||||
| main.go:93:13:93:13 | a | main.go:93:6:93:6 | assignment to b |
|
||||
| main.go:95:2:95:12 | return statement | main.go:88:1:96:1 | exit |
|
||||
| main.go:95:9:95:9 | a | main.go:95:12:95:12 | b |
|
||||
| main.go:95:12:95:12 | b | main.go:95:2:95:12 | return statement |
|
||||
| noretfunctions.go:0:0:0:0 | entry | noretfunctions.go:3:1:6:1 | skip |
|
||||
| noretfunctions.go:3:1:6:1 | skip | noretfunctions.go:8:6:8:12 | skip |
|
||||
| noretfunctions.go:8:1:10:1 | entry | noretfunctions.go:9:2:9:8 | selection of Exit |
|
||||
|
||||
@@ -53,16 +53,6 @@ func baz2() (result int) {
|
||||
return
|
||||
}
|
||||
|
||||
func baz3(selector int) (result int) {
|
||||
result = 0
|
||||
if selector == 1 {
|
||||
return 1
|
||||
} else {
|
||||
result = 2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func loops() {
|
||||
var x int
|
||||
for cond() {
|
||||
|
||||
@@ -2,5 +2,3 @@
|
||||
| main.go:7:19:7:23 | ...+... | + | main.go:7:19:7:19 | y | main.go:7:23:7:23 | z |
|
||||
| main.go:10:14:10:18 | ...+... | + | main.go:10:14:10:14 | x | main.go:10:18:10:18 | y |
|
||||
| main.go:17:2:17:13 | ... += ... | + | main.go:17:2:17:6 | index expression | main.go:17:11:17:13 | "!" |
|
||||
| resultParameters.go:4:5:4:17 | ...==... | == | resultParameters.go:4:5:4:12 | selector | resultParameters.go:4:17:4:17 | 0 |
|
||||
| resultParameters.go:23:5:23:17 | ...==... | == | resultParameters.go:23:5:23:12 | selector | resultParameters.go:23:17:23:17 | 1 |
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
| main.go:21:9:21:10 | 23 | Result node with index 0 |
|
||||
| main.go:21:13:21:14 | 42 | Result node with index 1 |
|
||||
| resultParameters.go:5:10:5:10 | 0 | Result node with index 0 |
|
||||
| resultParameters.go:9:10:9:10 | 1 | Result node with index 0 |
|
||||
| resultParameters.go:11:10:11:10 | 2 | Result node with index 0 |
|
||||
| resultParameters.go:13:9:13:9 | 3 | Result node with index 0 |
|
||||
| resultParameters.go:16:26:16:26 | implicit read of r | Result node with index 0 |
|
||||
| resultParameters.go:21:38:21:38 | implicit read of r | Result node with index 0 |
|
||||
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* @kind problem
|
||||
* @id result-node
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
from DataFlow::ResultNode r
|
||||
select r, "Result node with index " + r.getIndex()
|
||||
@@ -1,2 +0,0 @@
|
||||
query: ResultNode.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -18,5 +18,5 @@ func f() {
|
||||
}
|
||||
|
||||
func test() (int, int) {
|
||||
return 23, 42 // $ Alert[result-node]
|
||||
return 23, 42
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package main
|
||||
|
||||
func multipleReturns(selector int) int {
|
||||
if selector == 0 {
|
||||
return 0 // $ Alert[result-node]
|
||||
}
|
||||
switch selector {
|
||||
case 1:
|
||||
return 1 // $ Alert[result-node]
|
||||
case 2:
|
||||
return 2 // $ Alert[result-node]
|
||||
}
|
||||
return 3 // $ Alert[result-node]
|
||||
}
|
||||
|
||||
func resultParameter1() (r int) { // $ Alert[result-node] // implicit reads of result parameters are located at the result parameter declaration
|
||||
r = 0
|
||||
return
|
||||
}
|
||||
|
||||
func resultParameter2(selector int) (r int) { // $ Alert[result-node] // implicit reads of result parameters are located at the result parameter declaration
|
||||
r = 0
|
||||
if selector == 1 {
|
||||
return 1
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -5,9 +5,9 @@
|
||||
| tests.go:15:3:15:3 | f | tests.go:46:5:46:76 | ... := ...[0] | tests.go:15:3:15:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:46:15:46:76 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:57:3:57:3 | f | tests.go:55:5:55:78 | ... := ...[0] | tests.go:57:3:57:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:55:15:55:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:69:3:69:3 | f | tests.go:67:5:67:76 | ... := ...[0] | tests.go:69:3:69:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:67:15:67:76 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:126:9:126:9 | f | tests.go:124:5:124:78 | ... := ...[0] | tests.go:126:9:126:9 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:124:15:124:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:145:3:145:3 | f | tests.go:141:5:141:78 | ... := ...[0] | tests.go:145:3:145:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:141:15:141:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:166:8:166:8 | f | tests.go:162:2:162:74 | ... := ...[0] | tests.go:166:8:166:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:162:12:162:74 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:111:9:111:9 | f | tests.go:109:5:109:78 | ... := ...[0] | tests.go:111:9:111:9 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:109:15:109:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:130:3:130:3 | f | tests.go:126:5:126:78 | ... := ...[0] | tests.go:130:3:130:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:126:15:126:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:151:8:151:8 | f | tests.go:147:2:147:74 | ... := ...[0] | tests.go:151:8:151:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:147:12:147:74 | call to OpenFile | call to OpenFile |
|
||||
edges
|
||||
| tests.go:9:24:9:24 | definition of f | tests.go:10:8:10:8 | f | provenance | |
|
||||
| tests.go:13:32:13:32 | definition of f | tests.go:14:13:16:2 | capture variable f | provenance | |
|
||||
@@ -22,9 +22,9 @@ edges
|
||||
| tests.go:48:29:48:29 | f | tests.go:13:32:13:32 | definition of f | provenance | |
|
||||
| tests.go:55:5:55:78 | ... := ...[0] | tests.go:57:3:57:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:67:5:67:76 | ... := ...[0] | tests.go:69:3:69:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:124:5:124:78 | ... := ...[0] | tests.go:126:9:126:9 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:141:5:141:78 | ... := ...[0] | tests.go:145:3:145:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:162:2:162:74 | ... := ...[0] | tests.go:166:8:166:8 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:109:5:109:78 | ... := ...[0] | tests.go:111:9:111:9 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:126:5:126:78 | ... := ...[0] | tests.go:130:3:130:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:147:2:147:74 | ... := ...[0] | tests.go:151:8:151:8 | f | provenance | Src:MaD:1 |
|
||||
models
|
||||
| 1 | Source: os; ; false; OpenFile; ; ; ReturnValue[0]; file; manual |
|
||||
nodes
|
||||
@@ -43,10 +43,10 @@ nodes
|
||||
| tests.go:57:3:57:3 | f | semmle.label | f |
|
||||
| tests.go:67:5:67:76 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:69:3:69:3 | f | semmle.label | f |
|
||||
| tests.go:124:5:124:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:126:9:126:9 | f | semmle.label | f |
|
||||
| tests.go:141:5:141:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:145:3:145:3 | f | semmle.label | f |
|
||||
| tests.go:162:2:162:74 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:166:8:166:8 | f | semmle.label | f |
|
||||
| tests.go:109:5:109:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:111:9:111:9 | f | semmle.label | f |
|
||||
| tests.go:126:5:126:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:130:3:130:3 | f | semmle.label | f |
|
||||
| tests.go:147:2:147:74 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:151:8:151:8 | f | semmle.label | f |
|
||||
subpaths
|
||||
|
||||
@@ -104,21 +104,6 @@ func deferredCloseWithSync() {
|
||||
}
|
||||
}
|
||||
|
||||
func deferredCloseWithSync2() {
|
||||
// open file for writing
|
||||
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
|
||||
// a call to `Close` is deferred, but we have a call to `Sync` later which
|
||||
// precedes the call to `Close` during execution
|
||||
defer f.Close()
|
||||
|
||||
if err := f.Sync(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
var a int
|
||||
_ = a
|
||||
}
|
||||
|
||||
func deferredCloseWithSyncEarlyReturn(n int) {
|
||||
// open file for writing
|
||||
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil { // $ Source
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(_env={"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true"})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, gradle_8_3, check_diagnostics_java):
|
||||
def test(codeql, java, gradle_8_3):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, gradle_8_3, check_diagnostics_java):
|
||||
def test(codeql, java, gradle_8_3):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
# gradlew has been rigged to stall for a long time by trying to fetch from a black-hole IP.
|
||||
# We should find the timeout logic fires and buildless aborts the Gradle run quickly.
|
||||
codeql.database.create(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, gradle_8_3, check_diagnostics_java):
|
||||
def test(codeql, java, gradle_8_3):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -3,7 +3,7 @@ import os
|
||||
import runs_on
|
||||
|
||||
|
||||
def test(codeql, java, cwd, check_diagnostics_java):
|
||||
def test(codeql, java, cwd):
|
||||
# This serves the "repo" directory on https://locahost:4443
|
||||
command = ["python3", "../server.py"]
|
||||
if runs_on.github_actions and runs_on.posix:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import os.path
|
||||
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(build_mode = "none",
|
||||
_env={
|
||||
"_JAVA_OPTIONS": "-Duser.home=" + os.path.join(os.getcwd(), "home-dir-with-maven-settings")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import os.path
|
||||
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(build_mode = "none",
|
||||
_env={
|
||||
"_JAVA_OPTIONS": "-Duser.home=" + os.path.join(os.getcwd(), "empty-home"),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
# mvnw has been rigged to stall for a long time by trying to fetch from a black-hole IP. We should find the timeout logic fires and buildless aborts the Maven run quickly.
|
||||
codeql.database.create(
|
||||
build_mode="none",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import os.path
|
||||
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(build_mode = "none",
|
||||
_env={
|
||||
"_JAVA_OPTIONS": "-Duser.home=" + os.path.join(os.getcwd(), "empty-home")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, codeql_mitm_proxy, gradle_8_3, check_diagnostics_java):
|
||||
def test(codeql, java, codeql_mitm_proxy, gradle_8_3):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, java, codeql_mitm_proxy, check_diagnostics_java):
|
||||
def test(codeql, java, codeql_mitm_proxy):
|
||||
codeql.database.create(
|
||||
_env={
|
||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def test(codeql, use_java_11, java, actions_toolchains_file, check_diagnostics_java):
|
||||
def test(codeql, use_java_11, java, actions_toolchains_file):
|
||||
# The version of gradle used doesn't work on java 17
|
||||
codeql.database.create(
|
||||
_env={
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
def test(codeql, java, check_diagnostics_java):
|
||||
def test(codeql, java):
|
||||
codeql.database.create(_env={"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true"})
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: Likely Bugs/Arithmetic/ConstantExpAppearsNonConstant.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
Likely Bugs/Arithmetic/ConstantExpAppearsNonConstant.ql
|
||||
@@ -84,10 +84,6 @@ private module Ast implements AstSig<Location> {
|
||||
|
||||
class DoStmt = J::DoStmt;
|
||||
|
||||
class UntilStmt extends LoopStmt {
|
||||
UntilStmt() { none() }
|
||||
}
|
||||
|
||||
final private class FinalForStmt = J::ForStmt;
|
||||
|
||||
class ForStmt extends FinalForStmt {
|
||||
@@ -121,18 +117,15 @@ private module Ast implements AstSig<Location> {
|
||||
final private class FinalTryStmt = J::TryStmt;
|
||||
|
||||
class TryStmt extends FinalTryStmt {
|
||||
AstNode getBody(int index) {
|
||||
result = super.getResource(index)
|
||||
or
|
||||
index = count(super.getAResource()) and
|
||||
result = super.getBlock()
|
||||
}
|
||||
Stmt getBody() { result = super.getBlock() }
|
||||
|
||||
CatchClause getCatch(int index) { result = super.getCatchClause(index) }
|
||||
|
||||
Stmt getFinally() { result = super.getFinally() }
|
||||
}
|
||||
|
||||
AstNode getTryInit(TryStmt try, int index) { result = try.getResource(index) }
|
||||
|
||||
final private class FinalCatchClause = J::CatchClause;
|
||||
|
||||
class CatchClause extends FinalCatchClause {
|
||||
|
||||
@@ -72,35 +72,6 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
}
|
||||
}
|
||||
|
||||
private class FlowNodeElement extends Element {
|
||||
FlowNodeElement() {
|
||||
this instanceof Field or
|
||||
this instanceof Expr or
|
||||
this instanceof Method
|
||||
}
|
||||
}
|
||||
|
||||
private predicate id(FlowNodeElement x, FlowNodeElement y) { x = y }
|
||||
|
||||
private predicate idOf(FlowNodeElement x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
|
||||
int getFlowNodeId(FlowNode n) {
|
||||
n =
|
||||
rank[result](FlowNode n0, int a, int b |
|
||||
a = 0 and
|
||||
idOf(n0.asField(), b)
|
||||
or
|
||||
// no case for `n0.asSsa()`; here we rely on the built-in location-based ranking
|
||||
a = 1 and
|
||||
idOf(n0.asExpr(), b)
|
||||
or
|
||||
a = 2 and
|
||||
idOf(n0.asMethod(), b)
|
||||
|
|
||||
n0 order by a, b
|
||||
)
|
||||
}
|
||||
|
||||
private SrcCallable viableCallable_v1(Call c) {
|
||||
result = viableImpl_v1(c)
|
||||
or
|
||||
@@ -194,8 +165,6 @@ private module Input implements TypeFlowInput<Location> {
|
||||
|
||||
class TypeFlowNode = FlowNode;
|
||||
|
||||
predicate getTypeFlowNodeId = FlowStepsInput::getFlowNodeId/1;
|
||||
|
||||
predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1;
|
||||
|
||||
class Type = RefType;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user