Compare commits

..

12 Commits

Author SHA1 Message Date
Calum Grant
2991069649 Add layering_check flag 2024-03-27 10:59:55 +00:00
Calum Grant
dcd8589967 Test 2024-03-26 13:20:59 +00:00
Calum Grant
dcc95bb860 Test 2024-03-26 13:05:01 +00:00
Calum Grant
0dd05ba854 Update abseil bazel modules 2024-03-26 11:55:44 +00:00
Calum Grant
17ec5211c4 Tweak build command 2024-03-26 11:42:44 +00:00
Calum Grant
7ea1191f5d Use recommended Bazel flags 2024-03-26 11:30:33 +00:00
Calum Grant
57eb6c13ed Fix typo 2024-03-26 11:23:59 +00:00
Calum Grant
b26acadc49 Set spawn-strategy=local 2024-03-26 11:18:50 +00:00
Calum Grant
c1a281f183 Tweak codeal-analysis.yml 2024-03-26 10:55:20 +00:00
Calum Grant
5a8af8b533 Update codeql-analysis.yml 2024-03-25 15:46:21 +00:00
Calum Grant
87fdf5f98f Update codeql-analysis.yml 2024-03-25 13:44:43 +00:00
Calum Grant
0775b78275 Compile Swift extractor 2024-03-25 12:35:15 +00:00
218 changed files with 198 additions and 1499 deletions

View File

@@ -40,7 +40,7 @@ jobs:
uses: github/codeql-action/init@main
# Override language selection by uncommenting this and choosing your languages
with:
languages: csharp
languages: csharp, cpp
config-file: ./.github/codeql/codeql-config.yml
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
@@ -57,6 +57,19 @@ jobs:
- run: |
dotnet build csharp
- name: "[Ubuntu] Remove GCC 13 from runner image"
shell: bash
run: |
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list
sudo apt-get update
sudo apt-get install -y --allow-downgrades libc6=2.35-* libc6-dev=2.35-* libstdc++6=12.3.0-* libgcc-s1=12.3.0-*
- name: "Build Swift extractor using Bazel"
run: |
bazel clean --expunge
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
bazel shutdown
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@main

View File

@@ -18,7 +18,7 @@ bazel_dep(name = "rules_pkg", version = "0.9.1")
bazel_dep(name = "rules_nodejs", version = "6.0.3")
bazel_dep(name = "rules_python", version = "0.31.0")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")

View File

@@ -28,6 +28,7 @@ provide:
- "misc/suite-helpers/qlpack.yml"
- "ruby/extractor-pack/codeql-extractor.yml"
- "swift/extractor-pack/codeql-extractor.yml"
- "swift/integration-tests/qlpack.yml"
- "ql/extractor-pack/codeql-extractor.yml"
- ".github/codeql/extensions/**/codeql-pack.yml"

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added new source models for the `Dapper` package. These models can be enabled by enabling the `database` threat model.

View File

@@ -58,54 +58,3 @@ extensions:
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync", "(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>)", "", "Argument[1]", "sql-injection", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync", "(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>)", "", "Argument[2]", "sql-injection", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync<T>", "(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>)", "", "Argument[1]", "sql-injection", "manual"]
- addsTo:
pack: codeql/csharp-all
extensible: sourceModel
data:
- ["Dapper", "SqlMapper", False, "ExecuteReader", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "ExecuteReaderAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "ExecuteScalar", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "ExecuteScalar<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "ExecuteScalarAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "ExecuteScalarAsync<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "Query<TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryAsync<TReturn>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirst", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirst<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirstAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirstAsync<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefault", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefault<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefaultAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefaultAsync<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryMultiple", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QueryMultipleAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingle", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingle<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleAsync<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefault", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefault<T>", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync", "", "", "ReturnValue", "database", "manual"]
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync<T>", "", "", "ReturnValue", "database", "manual"]
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["Dapper", "SqlMapper", False, "AsList<T>", "(System.Collections.Generic.IEnumerable<T>)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]

View File

@@ -1,7 +0,0 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data:
- ["database", true, 0]

View File

@@ -1,12 +0,0 @@
import csharp
import semmle.code.csharp.security.dataflow.flowsources.FlowSources
import TestUtilities.InlineFlowTest
import TaintFlowTest<DatabaseConfig>
module DatabaseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc | mc.getTarget().hasName("Sink") | sink.asExpr() = mc.getArgument(0))
}
}

View File

@@ -1,50 +0,0 @@
using System;
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Threading.Tasks;
using Dapper;
namespace Test
{
class UseDapper
{
public static void Bad01(string connectionString, string query)
{
using (var connection = new SqlConnection(connectionString))
{
var result = connection.Query<object>(query);
Sink(result); // $ hasTaintFlow=line:16
}
}
public static async Task Bad02(string connectionString, string query)
{
using (var connection = new SqlConnection(connectionString))
{
var result = await connection.QueryAsync<object>(query);
Sink(result); // $ hasTaintFlow=line:25
}
}
public static void Bad03(string connectionString, string query)
{
using (var connection = new SqlConnection(connectionString))
{
var result = connection.QueryFirst(query);
Sink(result); // $ hasTaintFlow=line:34
}
}
public static void Bad04(string connectionString, string query)
{
using (var connection = new SqlConnection(connectionString))
{
var results = connection.Query<object>(query).AsList();
Sink(results[0]); // $ hasTaintFlow=line:43
}
}
public static void Sink(object o) { }
}
}

View File

@@ -1,5 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../../resources/stubs/Dapper/2.1.24/Dapper.csproj
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../../resources/stubs/System.Data.SqlClient/4.8.5/System.Data.SqlClient.csproj
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../../resources/stubs/System.Data.SQLite/1.0.118/System.Data.SQLite.csproj
semmle-extractor-options: ${testdir}/../../../../../../resources/stubs/System.Windows.cs

View File

@@ -1,95 +1,4 @@
source
| Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Data.CommandBehavior);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.Common.DbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.Common.DbConnection,Dapper.CommandDefinition,System.Data.CommandBehavior);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.Common.DbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Data.CommandBehavior);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalar;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalar;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalar<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalar<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalarAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalarAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalarAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;ExecuteScalarAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;Query<TReturn>;(System.Data.IDbConnection,System.String,System.Type[],System.Func<System.Object[],TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TReturn>,System.String);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.String);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.String);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.String);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.String);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TReturn>,System.String);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryAsync<TReturn>;(System.Data.IDbConnection,System.String,System.Type[],System.Func<System.Object[],TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirst;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirst;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirst<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirst<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefault;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefault;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefault<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefault<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryMultiple;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryMultiple;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryMultipleAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QueryMultipleAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingle;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingle;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingle<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingle<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefault;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefault;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefault<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefault<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
| Microsoft.Extensions.Configuration;EnvironmentVariablesExtensions;false;AddEnvironmentVariables;(Microsoft.Extensions.Configuration.IConfigurationBuilder);;Argument[0];environment;manual |
| Microsoft.Extensions.Configuration;EnvironmentVariablesExtensions;false;AddEnvironmentVariables;(Microsoft.Extensions.Configuration.IConfigurationBuilder);;ReturnValue;environment;manual |
| Microsoft.Extensions.Configuration;EnvironmentVariablesExtensions;false;AddEnvironmentVariables;(Microsoft.Extensions.Configuration.IConfigurationBuilder,System.Action<Microsoft.Extensions.Configuration.EnvironmentVariables.EnvironmentVariablesConfigurationSource>);;Argument[0];environment;manual |
@@ -736,7 +645,6 @@ summary
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TReturn>;(System.Func<TFirst,TSecond,TThird,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper+GridReader;false;Read<TReturn>;(System.Type[],System.Func<System.Object[],TReturn>,System.String,System.Boolean);;Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper;false;AsList<T>;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue.Element;value;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |

View File

@@ -8,7 +8,6 @@
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TReturn>;(System.Func<TFirst,TSecond,TThird,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper+GridReader;false;Read<TReturn>;(System.Type[],System.Func<System.Object[],TReturn>,System.String,System.Boolean);;Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper;false;AsList<T>;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue.Element;value;manual |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |

View File

@@ -17,7 +17,7 @@
.NET 5, .NET 6, .NET 7, .NET 8","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
Go (aka Golang), "Go up to 1.22", "Go 1.11 or more recent", ``.go``
Java,"Java 7 to 22 [5]_","javac (OpenJDK and Oracle JDK),
Java,"Java 7 to 21 [5]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [6]_",``.java``
Kotlin [7]_,"Kotlin 1.5.0 to 1.9.2\ *x*","kotlinc",``.kt``
@@ -33,7 +33,7 @@
.. [2] Objective-C, Objective-C++, C++/CLI, and C++/CX are not supported.
.. [3] Support for the clang-cl compiler is preliminary.
.. [4] Support for the Arm Compiler (armcc) is preliminary.
.. [5] Builds that execute on Java 7 to 22 can be analyzed. The analysis understands Java 22 standard language features.
.. [5] Builds that execute on Java 7 to 21 can be analyzed. The analysis understands Java 21 standard language features.
.. [6] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin.
.. [7] Kotlin support is currently in beta.
.. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.

View File

@@ -5,21 +5,19 @@
<overview>
<p>
Code that constructs a quoted string literal containing user-provided data needs to ensure that
this data does not itself contain a quote. Otherwise the embedded data could (accidentally or
intentionally) terminate the string literal early and thereby change the structure of the overall
string, with potentially severe consequences. If, for example, the string is later used as
part of an operating-system command or database query, an attacker may be able to craft input data
that injects a malicious command.
Code that constructs a string containing a quoted substring needs to ensure that any user-provided
data embedded in between the quotes does not itself contain a quote. Otherwise the embedded data
could (accidentally or intentionally) change the structure of the overall string by terminating
the quoted substring early, with potentially severe consequences. If, for example, the string is
later interpreted as an operating-system command or database query, a malicious attacker may be
able to craft input data that enables a command injection or SQL injection attack.
</p>
</overview>
<recommendation>
<p>
Sanitize the embedded data appropriately to ensure quotes are escaped, or use an API that does
not rely on manually constructing quoted substrings. Make sure to use the appropriate escaping
mechanism, for example, double quoting for SQL strings or backslash escaping for shell commands.
When using backslash escaping, the backslash character itself must also be escaped.
not rely on manually constructing quoted substrings.
</p>
</recommendation>
@@ -31,38 +29,17 @@ then embeds it into a SQL query built using the Squirrel library.
</p>
<sample src="StringBreak.go"/>
<p>
Note that JSON encoding does not escape single quotes in any way, so this code is vulnerable: any
single-quote character in <code>version</code> will prematurely close the surrounding string literal,
changing the structure of the SQL expression being constructed. This could be exploited to mount
a SQL injection attack.
Note that while Squirrel provides a structured API for building SQL queries that mitigates against
common causes of SQL injection vulnerabilities, this code is still vulnerable: if the JSON-encoded
representation of <code>version</code> contains a single quote, this will prematurely close the
surrounding string, changing the structure of the SQL expression being constructed. This could be
exploited to mount a SQL injection attack.
</p>
<p>
To fix this vulnerability, use the placeholder syntax from Squirrel's structured API for building
queries, which avoids the need to explicitly construct a quoted string.
To fix this vulnerability, use Squirrel's placeholder syntax, which avoids the need to explicitly
construct a quoted string.
</p>
<sample src="StringBreakGood.go"/>
<p>
In situations where a structured API is not available, make sure that you escape quotes before embedding
user-provided data into a quoted string. For example, this is how you can backslash-escape single
quotes using <code>strings.ReplaceAll</code>:
</p>
<sample language="go">
quoted := strings.ReplaceAll(raw, `\`, `\\`)
quoted = strings.ReplaceAll(quoted, "'", "\\'")
</sample>
<p>
Note that any existing backslash characters in the string must be escaped first, so that they do
not interfere with the escaping of single quotes.
</p>
<p>
In some cases, <code>strconv.Quote</code> is a convenient option for backslash escaping, but note
that it has two limitations:
</p>
<ol>
<li>It only supports double quotes, not single quotes (as in the example).</li>
<li>It puts quotes around the entire string, so it can only be used to construct complete string
literals, not parts of larger string literals.</li>
</ol>
</example>
<references>

View File

@@ -49,15 +49,6 @@ predicate gapInChildren(Element e, int i) {
not e instanceof Annotation and
// Pattern case statements legitimately have a TypeAccess (-2) and a pattern (0) but not a rule (-1)
not (i = -1 and e instanceof PatternCase and not e.(PatternCase).isRule()) and
// Pattern case statements can have a gap at -3 when they have more than one pattern but no guard.
not (
i = -3 and count(e.(PatternCase).getAPattern()) > 1 and not exists(e.(PatternCase).getGuard())
) and
// Pattern case statements may have some missing type accesses, depending on the nature of the direct child
not (
(i = -2 or i < -4) and
e instanceof PatternCase
) and
// Instanceof with a record pattern is not expected to have a type access in position 1
not (i = 1 and e.(InstanceOfExpr).getPattern() instanceof RecordPatternExpr) and
// RecordPatternExpr extracts type-accesses only for its LocalVariableDeclExpr children

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/java-all
pack: integrationtest-default-parameter-mad-flow
extensible: summaryModel
data:
- ["", "ConstructorWithDefaults", True, "ConstructorWithDefaults", "(int,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
@@ -11,14 +11,14 @@ extensions:
- ["", "LibClass", True, "multiParameterTest", "(int,int,int,int)", "", "Argument[0..1]", "ReturnValue", "value", "manual"]
- ["", "LibClass", True, "multiParameterExtensionTest", "(int,int,int,int)", "", "Argument[0, 1]", "ReturnValue", "value", "manual"]
- addsTo:
pack: codeql/java-all
pack: integrationtest-default-parameter-mad-flow
extensible: sourceModel
data:
- ["", "LibKt", True, "topLevelArgSource", "(SomeToken,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"]
- ["", "LibKt", True, "extensionArgSource", "(String,SomeToken,int)", "", "Argument[1]", "kotlinMadFlowTest", "manual"]
- ["", "SourceClass", True, "memberArgSource", "(SomeToken,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"]
- addsTo:
pack: codeql/java-all
pack: integrationtest-default-parameter-mad-flow
extensible: sinkModel
data:
- ["", "SinkClass", True, "SinkClass", "(int,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"]

View File

@@ -1,5 +0,0 @@
---
category: minorAnalysis
---
* The Java extractor and QL libraries now support Java 22, including support for anonymous variables, lambda parameters and patterns.
* Pattern cases with multiple patterns and that fall through to or from other pattern cases are now supported. The `PatternCase` class gains the new `getPatternAtIndex` and `getAPattern` predicates, and deprecates `getPattern`.

View File

@@ -489,14 +489,14 @@ private module ControlFlowGraphImpl {
private Stmt getSwitchStatement(SwitchBlock switch, int i) { result.isNthChildOf(switch, i) }
/**
* Holds if `last` is the last node in any of pattern case `pc`'s succeeding bind-and-test operations,
* Holds if `last` is the last node in a pattern case `pc`'s succeeding bind-and-test operation,
* immediately before either falling through to execute successor statements or execute a rule body
* if present. `completion` is the completion kind of the last operation.
*/
private predicate lastPatternCaseMatchingOp(
PatternCase pc, ControlFlowNode last, Completion completion
) {
last(pc.getAPattern(), last, completion) and
last(pc.getPattern(), last, completion) and
completion = NormalCompletion() and
not exists(pc.getGuard())
or
@@ -776,18 +776,6 @@ private module ControlFlowGraphImpl {
last(try.getFinally(), last, NormalCompletion())
}
private predicate isNextNormalSwitchStmt(SwitchBlock switch, Stmt pred, Stmt succ) {
exists(int i, Stmt immediateSucc |
getSwitchStatement(switch, i) = pred and
getSwitchStatement(switch, i + 1) = immediateSucc and
(
if immediateSucc instanceof PatternCase
then isNextNormalSwitchStmt(switch, immediateSucc, succ)
else succ = immediateSucc
)
)
}
/**
* Bind `last` to a cfg node nested inside `n` (or, indeed, `n` itself) such
* that `last` may be the last node during an execution of `n` and finish
@@ -939,15 +927,9 @@ private module ControlFlowGraphImpl {
completion != anonymousBreakCompletion() and
not completion instanceof NormalOrBooleanCompletion
or
// if a statement without a non-pattern-case successor completes normally (or for a pattern case
// the guard succeeds) then the switch completes normally.
exists(Stmt lastNormalStmt, Completion stmtCompletion |
lastNormalStmt = getSwitchStatement(switch, _) and
not isNextNormalSwitchStmt(switch, lastNormalStmt, _) and
last(lastNormalStmt, last, stmtCompletion) and
(stmtCompletion = NormalCompletion() or stmtCompletion = BooleanCompletion(true, _)) and
completion = NormalCompletion()
)
// if the last case completes normally, then so does the switch
last(switch.getStmt(strictcount(switch.getAStmt()) - 1), last, NormalCompletion()) and
completion = NormalCompletion()
or
// if no default case exists, then normal completion of the expression may terminate the switch
// Note this can't happen if there are pattern cases or a null literal, as
@@ -991,9 +973,9 @@ private module ControlFlowGraphImpl {
)
or
// A pattern case statement can complete:
// * On failure of its final type test (boolean false)
// * On failure of its type test (boolean false)
// * On failure of its guard test if any (boolean false)
// * On completion of one of its pattern variable declarations, if it is not a rule and has no guard (normal completion)
// * On completion of its variable declarations, if it is not a rule and has no guard (normal completion)
// * On success of its guard test, if it is not a rule (boolean true)
// (the latter two cases are accounted for by lastPatternCaseMatchingOp)
exists(PatternCase pc | n = pc |
@@ -1333,13 +1315,9 @@ private module ControlFlowGraphImpl {
// Note this includes non-rule case statements and the successful pattern match successor
// of a non-rule pattern case statement. Rule case statements do not complete normally
// (they always break or yield).
// Exception: falling through into a pattern case statement (which necessarily does not
// declare any named variables) must skip one or more such statements, otherwise we would
// incorrectly apply their type test and/or guard.
exists(Stmt pred, Stmt succ |
isNextNormalSwitchStmt(switch, pred, succ) and
last(pred, n, completion) and
result = first(succ) and
exists(int i |
last(getSwitchStatement(switch, i), n, completion) and
result = first(getSwitchStatement(switch, i + 1)) and
(completion = NormalCompletion() or completion = BooleanCompletion(true, _))
)
or
@@ -1350,19 +1328,16 @@ private module ControlFlowGraphImpl {
)
or
// Pattern cases have internal edges:
// * Type test success -true-> one of the possible sets of variable declarations
// n.b. for unnamed patterns (e.g. case A _, B _) this means that *one* of the
// type tests has succeeded. There aren't enough nodes in the AST to describe
// a sequential test in detail, so CFG consumers have to watch out for this case.
// * Type test success -true-> variable declarations
// * Variable declarations -normal-> guard evaluation
// * Variable declarations -normal-> rule execution (when there is no guard)
// * Guard success -true-> rule execution
exists(PatternCase pc |
n = pc and
completion = basicBooleanCompletion(true) and
result = first(pc.getAPattern())
result = first(pc.getPattern())
or
last(pc.getAPattern(), n, completion) and
last(pc.getPattern(), n, completion) and
completion = NormalCompletion() and
result = first(pc.getGuard())
or

View File

@@ -84,7 +84,7 @@ predicate depends(RefType t, RefType dep) {
or
// A type accessed in a pattern-switch case statement in `t`.
exists(PatternCase pc | t = pc.getEnclosingCallable().getDeclaringType() |
usesType(pc.getAPattern().getAChildExpr*().getType(), dep)
usesType(pc.getPattern().getAChildExpr*().getType(), dep)
)
)
}

View File

@@ -107,7 +107,7 @@ predicate numDepends(RefType t, RefType dep, int value) {
or
// the type accessed in a pattern-switch case statement in `t`.
exists(PatternCase pc | elem = pc and t = pc.getEnclosingCallable().getDeclaringType() |
usesType(pc.getAPattern().getAChildExpr*().getType(), dep)
usesType(pc.getPattern().getAChildExpr*().getType(), dep)
)
)
}

View File

@@ -1590,9 +1590,7 @@ class InstanceOfExpr extends Expr, @instanceofexpr {
* Note that this won't get anything when record pattern matching is used-- for more general patterns,
* use `getPattern`.
*/
LocalVariableDeclExpr getLocalVariableDeclExpr() {
result = this.getPattern().asBindingOrUnnamedPattern()
}
LocalVariableDeclExpr getLocalVariableDeclExpr() { result = this.getPattern().asBindingPattern() }
/**
* Gets the access to the type on the right-hand side of the `instanceof` operator.
@@ -1683,10 +1681,7 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
or
exists(InstanceOfExpr ioe | this.getParent() = ioe | result.isNthChildOf(ioe, 1))
or
exists(PatternCase pc, int index, int typeAccessIdx | this.isNthChildOf(pc, index) |
(if index = 0 then typeAccessIdx = -2 else typeAccessIdx = (-3 - index)) and
result.isNthChildOf(pc, typeAccessIdx)
)
exists(PatternCase pc | this.getParent() = pc | result.isNthChildOf(pc, -2))
or
exists(RecordPatternExpr rpe, int index |
this.isNthChildOf(rpe, index) and result.isNthChildOf(rpe, -(index + 1))
@@ -1696,9 +1691,6 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
/** Gets the name of the variable declared by this local variable declaration expression. */
string getName() { result = this.getVariable().getName() }
/** Holds if this is an anonymous local variable, `_` */
predicate isAnonymous() { this.getName() = "" }
/**
* Gets the switch statement or expression whose pattern declares this identifier, if any.
*/
@@ -1708,7 +1700,7 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
or
pc = result.(SwitchExpr).getAPatternCase()
|
this = pc.getAPattern().getAChildExpr*()
this = pc.getPattern().getAChildExpr*()
)
}
@@ -1747,17 +1739,17 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
or
exists(SwitchStmt switch |
result = switch.getExpr() and
this = switch.getAPatternCase().getAPattern().asBindingOrUnnamedPattern()
this = switch.getAPatternCase().getPattern().asBindingPattern()
)
or
exists(SwitchExpr switch |
result = switch.getExpr() and
this = switch.getAPatternCase().getAPattern().asBindingOrUnnamedPattern()
this = switch.getAPatternCase().getPattern().asBindingPattern()
)
or
exists(InstanceOfExpr ioe |
result = ioe.getExpr() and
this = ioe.getPattern().asBindingOrUnnamedPattern()
this = ioe.getPattern().asBindingPattern()
)
}
@@ -1771,9 +1763,7 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
}
/** Gets a printable representation of this expression. */
override string toString() {
if this.getName() = "" then result = "<anonymous local variable>" else result = this.getName()
}
override string toString() { result = this.getName() }
override string getAPrimaryQlClass() { result = "LocalVariableDeclExpr" }
}
@@ -2681,9 +2671,9 @@ class NotNullExpr extends UnaryExpr, @notnullexpr {
}
/**
* A binding, unnamed or record pattern.
* A binding or record pattern.
*
* Note binding and unnamed patterns are represented as `LocalVariableDeclExpr`s.
* Note binding patterns are represented as `LocalVariableDeclExpr`s.
*/
class PatternExpr extends Expr {
PatternExpr() {
@@ -2696,14 +2686,9 @@ class PatternExpr extends Expr {
}
/**
* Gets this pattern cast to a binding or unnamed pattern.
* Gets this pattern cast to a binding pattern.
*/
LocalVariableDeclExpr asBindingOrUnnamedPattern() { result = this }
/**
* DEPRECATED: alias for `asBindingOrUnnamedPattern`.
*/
deprecated LocalVariableDeclExpr asBindingPattern() { result = this.asBindingOrUnnamedPattern() }
LocalVariableDeclExpr asBindingPattern() { result = this }
/**
* Gets this pattern cast to a record pattern.
@@ -2739,14 +2724,4 @@ class RecordPatternExpr extends Expr, @recordpatternexpr {
)
)
}
/**
* Holds if this record pattern declares any identifiers (i.e., at least one leaf declaration is named).
*/
predicate declaresAnyIdentifiers() {
exists(PatternExpr subPattern | subPattern = this.getSubPattern(_) |
subPattern.asRecordPattern().declaresAnyIdentifiers() or
not subPattern.asBindingOrUnnamedPattern().isAnonymous()
)
}
}

View File

@@ -386,7 +386,7 @@ private class PpInstanceOfExpr extends PpAst, InstanceOfExpr {
i = 3 and result = " " and this.getPattern() instanceof LocalVariableDeclExpr
or
i = 4 and
result = this.getPattern().asBindingOrUnnamedPattern().getName()
result = this.getPattern().asBindingPattern().getName()
}
override PpAst getChild(int i) {
@@ -400,8 +400,7 @@ private class PpInstanceOfExpr extends PpAst, InstanceOfExpr {
private class PpLocalVariableDeclExpr extends PpAst, LocalVariableDeclExpr {
override string getPart(int i) {
i = 0 and
(if this.isAnonymous() then result = "_" else result = this.getName())
i = 0 and result = this.getName()
or
i = 1 and result = " = " and exists(this.getInit())
}
@@ -783,54 +782,28 @@ private class PpSwitchCase extends PpAst, SwitchCase {
}
private class PpPatternCase extends PpAst, PatternCase {
private predicate isAnonymousPattern(int n) {
this.getPattern(n).asBindingOrUnnamedPattern().isAnonymous()
}
override string getPart(int i) {
exists(int n, int base | exists(this.getPattern(n)) and base = n * 4 |
i = base and
(if n = 0 then result = "case " else result = ", ")
or
i = base + 2 and
this.getPattern(n) instanceof LocalVariableDeclExpr and
(
exists(this.getPattern(n).asBindingOrUnnamedPattern().getTypeAccess())
or
not this.isAnonymousPattern(n)
) and
result = " "
or
i = base + 3 and
(
if this.isAnonymousPattern(n)
then result = "_"
else result = this.getPattern(n).asBindingOrUnnamedPattern().getName()
)
)
i = 0 and result = "case "
or
exists(int base | base = (max(int n | exists(this.getPattern(n))) + 1) * 4 |
i = base and result = ":" and not this.isRule()
or
i = base and result = " -> " and this.isRule()
or
i = base + 2 and result = ";" and exists(this.getRuleExpression())
)
i = 2 and this.getPattern() instanceof LocalVariableDeclExpr and result = " "
or
i = 3 and result = this.getPattern().asBindingPattern().getName()
or
i = 4 and result = ":" and not this.isRule()
or
i = 4 and result = " -> " and this.isRule()
or
i = 6 and result = ";" and exists(this.getRuleExpression())
}
override PpAst getChild(int i) {
exists(int n, int base | exists(this.getPattern(n)) and base = n * 4 |
i = base + 1 and
result = this.getPattern(n).asBindingOrUnnamedPattern().getTypeAccess()
or
i = base + 1 and result = this.getPattern(n).asRecordPattern()
)
i = 1 and result = this.getPattern().asBindingPattern().getTypeAccess()
or
exists(int base | base = (max(int n | exists(this.getPattern(n))) + 1) * 4 |
i = base + 1 and result = this.getRuleExpression()
or
i = base + 1 and result = this.getRuleStatement()
)
i = 1 and result = this.getPattern().asRecordPattern()
or
i = 5 and result = this.getRuleExpression()
or
i = 5 and result = this.getRuleStatement()
}
}

View File

@@ -117,11 +117,7 @@ private newtype TPrintAstNode =
TElementNode(Element el) { shouldPrint(el, _) } or
TForInitNode(ForStmt fs) { shouldPrint(fs, _) and exists(fs.getAnInit()) } or
TLocalVarDeclNode(LocalVariableDeclExpr lvde) {
shouldPrint(lvde, _) and
(
lvde.getParent() instanceof SingleLocalVarDeclParent or
lvde.getParent() instanceof PatternCase
)
shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent
} or
TAnnotationsNode(Annotatable ann) {
shouldPrint(ann, _) and
@@ -419,23 +415,6 @@ final class ForStmtNode extends ExprStmtNode {
}
}
/**
* A node representing a `PatternCase`.
*/
final class PatternCaseNode extends ExprStmtNode {
PatternCase pc;
PatternCaseNode() { pc = element }
override PrintAstNode getChild(int childIndex) {
result = super.getChild(childIndex) and
not result.(ElementNode).getElement() instanceof LocalVariableDeclExpr and
not result.(ElementNode).getElement() instanceof TypeAccess
or
result = TLocalVarDeclNode(pc.getPattern(childIndex))
}
}
/**
* An element that can be the parent of up to one `LocalVariableDeclExpr` for which we want
* to use a synthetic node to hold the variable declaration and its `TypeAccess`.
@@ -444,7 +423,8 @@ private class SingleLocalVarDeclParent extends ExprOrStmt {
SingleLocalVarDeclParent() {
this instanceof EnhancedForStmt or
this instanceof CatchClause or
this.(InstanceOfExpr).isPattern()
this.(InstanceOfExpr).isPattern() or
this instanceof PatternCase
}
/** Gets the variable declaration that this element contains */
@@ -459,7 +439,7 @@ private class SingleLocalVarDeclParent extends ExprOrStmt {
* want to use a synthetic node to variable declaration and its type access.
*
* Excludes `LocalVariableDeclStmt` and `ForStmt`, as they can hold multiple declarations.
* For these cases, either a synthetic node is not necessary or a different synthetic node is used.
* For these cases, either a synthetic node is not necassary or a different synthetic node is used.
*/
final class SingleLocalVarDeclParentNode extends ExprStmtNode {
SingleLocalVarDeclParent lvdp;
@@ -663,11 +643,7 @@ final class LocalVarDeclSynthNode extends PrintAstNode, TLocalVarDeclNode {
LocalVarDeclSynthNode() { this = TLocalVarDeclNode(lvde) }
override string toString() {
if lvde.getParent() instanceof PatternCase
then result = "(Pattern case declaration)"
else result = "(Single Local Variable Declaration)"
}
override string toString() { result = "(Single Local Variable Declaration)" }
override ElementNode getChild(int childIndex) {
childIndex = 0 and

View File

@@ -539,27 +539,12 @@ class ConstCase extends SwitchCase {
/** A pattern case of a `switch` statement */
class PatternCase extends SwitchCase {
PatternCase() { exists(PatternExpr pe | pe.isNthChildOf(this, _)) }
PatternExpr pattern;
/**
* DEPRECATED: alias for getPattern(0)
*/
deprecated PatternExpr getPattern() { result = this.getPattern(0) }
PatternCase() { pattern.isNthChildOf(this, 0) }
/**
* Gets this case's `n`th pattern.
*/
PatternExpr getPattern(int n) { result.isNthChildOf(this, n) }
/**
* Gets any of this case's patterns.
*/
PatternExpr getAPattern() { result = this.getPattern(_) }
/**
* Gets this case's sole pattern, if there is exactly one.
*/
PatternExpr getUniquePattern() { result = unique(PatternExpr pe | pe = this.getAPattern()) }
/** Gets this case's pattern. */
PatternExpr getPattern() { result = pattern }
/** Gets the guard applicable to this pattern case, if any. */
Expr getGuard() { result.isNthChildOf(this, -3) }

View File

@@ -58,13 +58,7 @@ class LocalVariableDecl extends @localvar, LocalScopeVariable {
/** Gets the callable in which this declaration occurs. */
Callable getEnclosingCallable() { result = this.getCallable() }
override string toString() {
exists(string sourceName |
if this.getName() = "" then sourceName = "_" else sourceName = this.getName()
|
result = this.getType().getName() + " " + sourceName
)
}
override string toString() { result = this.getType().getName() + " " + this.getName() }
/** Gets the initializer expression of this local variable declaration. */
override Expr getInitializer() { result = this.getDeclExpr().getInit() }
@@ -123,11 +117,4 @@ class Parameter extends Element, @param, LocalScopeVariable {
}
override string getAPrimaryQlClass() { result = "Parameter" }
override string toString() {
if this.getName() = "" then result = "<anonymous parameter>" else result = super.toString()
}
/** Holds if this is an anonymous parameter, `_` */
predicate isAnonymous() { this.getName() = "" }
}

View File

@@ -115,24 +115,8 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
(
pred.(Expr).getParent*() = sc.getSelectorExpr()
or
// Ambiguous: in the case of `case String _ when x: case "SomeConstant":`, the guard `x`
// passing edge will fall through into the constant case, and the guard failing edge
// will test if the selector equals `"SomeConstant"` and if so branch to the same
// case statement. Therefore don't label this a non-fall-through predecessor.
exists(PatternCase previousPatternCase |
previousPatternCase = getClosestPrecedingPatternCase(sc)
|
pred.(Expr).getParent*() = previousPatternCase.getGuard() and
// Check there is any statement in between the previous pattern case and this one,
// or the case is a rule, so there is no chance of a fall-through.
(
previousPatternCase.isRule() or
not previousPatternCase.getIndex() = sc.getIndex() - 1
)
)
pred.(Expr).getParent*() = getClosestPrecedingPatternCase(sc).getGuard()
or
// Unambigious: on the test-passing edge there must be at least one intervening
// declaration node, including anonymous `_` declarations.
pred = getClosestPrecedingPatternCase(sc)
)
}
@@ -217,13 +201,13 @@ class Guard extends ExprParent {
or
exists(PatternCase pc | this = pc |
pc.getSelectorExpr() = testedExpr and
testedType = pc.getUniquePattern().getType()
testedType = pc.getPattern().getType()
)
) and
(
if
exists(RecordPatternExpr rpe |
rpe = [this.(InstanceOfExpr).getPattern(), this.(PatternCase).getAPattern()]
rpe = [this.(InstanceOfExpr).getPattern(), this.(PatternCase).getPattern()]
|
not rpe.isUnrestricted()
)

View File

@@ -194,17 +194,12 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
// In the following three cases only record patterns need this flow edge, leading from the bound instanceof
// or switch tested expression to a record pattern that will read its fields. Simple binding patterns are
// handled via VariableAssign.getSource instead.
// We only consider patterns that declare any identifiers
exists(SwitchExpr se, RecordPatternExpr recordPattern | recordPattern = e2 |
e1 = se.getExpr() and
recordPattern = se.getACase().(PatternCase).getAPattern() and
recordPattern.declaresAnyIdentifiers()
exists(SwitchExpr se |
e1 = se.getExpr() and e2 = se.getACase().(PatternCase).getPattern().asRecordPattern()
)
or
exists(SwitchStmt ss, RecordPatternExpr recordPattern | recordPattern = e2 |
e1 = ss.getExpr() and
recordPattern = ss.getACase().(PatternCase).getAPattern() and
recordPattern.declaresAnyIdentifiers()
exists(SwitchStmt ss |
e1 = ss.getExpr() and e2 = ss.getACase().(PatternCase).getPattern().asRecordPattern()
)
or
exists(InstanceOfExpr ioe | e1 = ioe.getExpr() and e2 = ioe.getPattern().asRecordPattern())

View File

@@ -1,5 +1,10 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: supportedThreatModels
data: []
- addsTo:
pack: codeql/java-all
extensible: sourceModel

View File

@@ -63,7 +63,7 @@ dependency/A.java:
# 31| 1: [SwitchStmt] switch (...)
# 31| -1: [VarAccess] o
# 32| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 32| 0: [TypeAccess] Used2
# 32| 1: [LocalVariableDeclExpr] u2
# 32| 1: [BreakStmt] break
@@ -74,7 +74,7 @@ dependency/A.java:
# 35| 0: [SwitchExpr] switch (...)
# 35| -1: [VarAccess] o
# 36| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 36| 0: [TypeAccess] Used3
# 36| 1: [LocalVariableDeclExpr] u3
# 36| 1: [YieldStmt] yield ...

View File

@@ -52,9 +52,9 @@ Test.java:
# 17| 0: [VarAccess] len
# 17| 1: [IntegerLiteral] 4
# 17| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 17| 0: [TypeAccess] String
# 17| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 17| 1: [LocalVariableDeclExpr] s2
# 18| 1: [ConstCase] case ...
# 18| -1: [BlockStmt] { ... }
# 18| 0: [StringLiteral] "e"
@@ -74,7 +74,7 @@ Test.java:
# 23| 0: [VarAccess] len
# 23| 1: [IntegerLiteral] 4
# 23| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 23| 0: [TypeAccess] String
# 23| 1: [LocalVariableDeclExpr] s2
# 24| 2: [ConstCase] case ...
@@ -82,23 +82,3 @@ Test.java:
# 24| 0: [StringLiteral] "g"
# 25| 3: [DefaultCase] default
# 25| -1: [BlockStmt] { ... }
# 27| 5: [SwitchStmt] switch (...)
# 27| -1: [VarAccess] s
# 28| 0: [ConstCase] case ...
# 28| 0: [StringLiteral] "h"
# 29| 1: [PatternCase] case <Pattern>
# 29| -3: [EQExpr] ... == ...
# 29| 0: [VarAccess] len
# 29| 1: [IntegerLiteral] 4
#-----| 0: (Pattern case declaration)
# 29| 0: [TypeAccess] String
# 29| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 30| 2: [ConstCase] case ...
# 30| 0: [StringLiteral] "i"
# 31| 3: [LocalVariableDeclStmt] var ...;
# 31| 0: [TypeAccess] String
# 31| 1: [LocalVariableDeclExpr] target
# 31| 0: [StringLiteral] "Shouldn't be controlled by any of those tests"
# 32| 4: [BreakStmt] break
# 33| 5: [DefaultCase] default
# 34| 6: [BreakStmt] break

View File

@@ -14,7 +14,7 @@ class Test {
}
int len = s.length();
switch (s) {
case String _ when len == 4 -> { }
case String s2 when len == 4 -> { }
case "e" -> { }
default -> { }
}
@@ -24,14 +24,5 @@ class Test {
case "g" -> { }
default -> { }
}
switch (s) {
case "h":
case String _ when len == 4:
case "i":
String target = "Shouldn't be controlled by any of those tests";
break;
default:
break;
}
}
}

View File

@@ -1,22 +1,22 @@
hasBranchEdge
| Test.java:4:7:4:22 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:4:7:4:22 | case ... | true |
| Test.java:5:7:5:17 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:5:7:5:17 | case ... | true |
| Test.java:6:7:6:17 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:6:7:6:17 | case ... | true |
| Test.java:7:7:7:16 | default | Test.java:2:39:36:3 | { ... } | Test.java:7:7:7:16 | default | true |
| Test.java:4:7:4:22 | case ... | Test.java:2:39:27:3 | { ... } | Test.java:4:7:4:22 | case ... | true |
| Test.java:5:7:5:17 | case ... | Test.java:2:39:27:3 | { ... } | Test.java:5:7:5:17 | case ... | true |
| Test.java:6:7:6:17 | case ... | Test.java:2:39:27:3 | { ... } | Test.java:6:7:6:17 | case ... | true |
| Test.java:7:7:7:16 | default | Test.java:2:39:27:3 | { ... } | Test.java:7:7:7:16 | default | true |
| Test.java:10:7:10:22 | case ... | Test.java:3:9:3:21 | x | Test.java:10:7:10:22 | case ... | true |
| Test.java:11:7:11:17 | case ... | Test.java:3:9:3:21 | x | Test.java:11:7:11:17 | case ... | true |
| Test.java:12:7:12:17 | case ... | Test.java:3:9:3:21 | x | Test.java:12:7:12:17 | case ... | true |
| Test.java:13:7:13:16 | default | Test.java:3:9:3:21 | x | Test.java:13:7:13:16 | default | true |
| Test.java:17:7:17:36 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:17:19:17:19 | <anonymous local variable> | true |
| Test.java:17:7:17:36 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | false |
| Test.java:17:7:17:36 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | false |
| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:17:38:17:40 | { ... } | true |
| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:18:7:18:17 | case ... | false |
| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:19:7:19:16 | default | false |
| Test.java:17:7:17:37 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:17:19:17:20 | s2 | true |
| Test.java:17:7:17:37 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | false |
| Test.java:17:7:17:37 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | false |
| Test.java:17:27:17:34 | ... == ... | Test.java:17:19:17:20 | s2 | Test.java:17:39:17:41 | { ... } | true |
| Test.java:17:27:17:34 | ... == ... | Test.java:17:19:17:20 | s2 | Test.java:18:7:18:17 | case ... | false |
| Test.java:17:27:17:34 | ... == ... | Test.java:17:19:17:20 | s2 | Test.java:19:7:19:16 | default | false |
| Test.java:18:7:18:17 | case ... | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | true |
| Test.java:18:7:18:17 | case ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:18:7:18:17 | case ... | true |
| Test.java:18:7:18:17 | case ... | Test.java:17:19:17:20 | s2 | Test.java:18:7:18:17 | case ... | true |
| Test.java:19:7:19:16 | default | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | true |
| Test.java:19:7:19:16 | default | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:19:7:19:16 | default | true |
| Test.java:19:7:19:16 | default | Test.java:17:19:17:20 | s2 | Test.java:19:7:19:16 | default | true |
| Test.java:21:13:21:19 | unknown | Test.java:21:5:21:42 | switch (...) | Test.java:21:23:21:23 | s | true |
| Test.java:21:13:21:19 | unknown | Test.java:21:5:21:42 | switch (...) | Test.java:21:27:21:27 | s | false |
| Test.java:22:7:22:17 | case ... | Test.java:21:23:21:23 | s | Test.java:22:7:22:17 | case ... | true |
@@ -31,16 +31,6 @@ hasBranchEdge
| Test.java:24:7:24:17 | case ... | Test.java:23:19:23:20 | s2 | Test.java:24:7:24:17 | case ... | true |
| Test.java:25:7:25:16 | default | Test.java:23:7:23:37 | case <Pattern> | Test.java:25:7:25:16 | default | true |
| Test.java:25:7:25:16 | default | Test.java:23:19:23:20 | s2 | Test.java:25:7:25:16 | default | true |
| Test.java:28:7:28:15 | case ... | Test.java:27:5:27:14 | switch (...) | Test.java:28:7:28:15 | case ... | true |
| Test.java:29:7:29:34 | case <Pattern> | Test.java:29:7:29:34 | case <Pattern> | Test.java:29:19:29:19 | <anonymous local variable> | true |
| Test.java:29:7:29:34 | case <Pattern> | Test.java:29:7:29:34 | case <Pattern> | Test.java:30:7:30:15 | case ... | false |
| Test.java:29:7:29:34 | case <Pattern> | Test.java:29:7:29:34 | case <Pattern> | Test.java:33:7:33:14 | default | false |
| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:30:7:30:15 | case ... | false |
| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:30:7:30:15 | case ... | true |
| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:33:7:33:14 | default | false |
| Test.java:30:7:30:15 | case ... | Test.java:29:7:29:34 | case <Pattern> | Test.java:30:7:30:15 | case ... | true |
| Test.java:33:7:33:14 | default | Test.java:29:7:29:34 | case <Pattern> | Test.java:33:7:33:14 | default | true |
| Test.java:33:7:33:14 | default | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:33:7:33:14 | default | true |
#select
| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | false | Test.java:7:7:7:16 | default |
| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | true | Test.java:5:7:5:17 | case ... |
@@ -50,7 +40,7 @@ hasBranchEdge
| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | true | Test.java:11:7:11:17 | case ... |
| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | false | Test.java:13:7:13:16 | default |
| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | true | Test.java:12:7:12:17 | case ... |
| Test.java:17:26:17:33 | ... == ... | Test.java:17:26:17:28 | len | Test.java:17:33:17:33 | 4 | true | true | Test.java:17:38:17:40 | { ... } |
| Test.java:17:27:17:34 | ... == ... | Test.java:17:27:17:29 | len | Test.java:17:34:17:34 | 4 | true | true | Test.java:17:39:17:41 | { ... } |
| Test.java:18:7:18:17 | case ... | Test.java:16:13:16:13 | s | Test.java:18:12:18:14 | "e" | true | false | Test.java:19:7:19:16 | default |
| Test.java:18:7:18:17 | case ... | Test.java:16:13:16:13 | s | Test.java:18:12:18:14 | "e" | true | true | Test.java:18:7:18:17 | case ... |
| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:25:7:25:16 | default |
@@ -58,6 +48,3 @@ hasBranchEdge
| Test.java:23:27:23:34 | ... == ... | Test.java:23:27:23:29 | len | Test.java:23:34:23:34 | 4 | true | true | Test.java:23:39:23:41 | { ... } |
| Test.java:24:7:24:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:24:12:24:14 | "g" | true | false | Test.java:25:7:25:16 | default |
| Test.java:24:7:24:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:24:12:24:14 | "g" | true | true | Test.java:24:7:24:17 | case ... |
| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:33:7:33:14 | default |
| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | true | Test.java:28:7:28:15 | case ... |
| Test.java:30:7:30:15 | case ... | Test.java:27:13:27:13 | s | Test.java:30:12:30:14 | "i" | true | false | Test.java:33:7:33:14 | default |

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args --release 22
//semmle-extractor-options: --javac-args --release 21

View File

@@ -26,12 +26,6 @@ public class Exhaustive {
case Y y -> { }
}
// Test the case where a pattern case falls directly out of a block:
switch (i) {
case X _:
case Y _:
}
}
}

View File

@@ -98,39 +98,6 @@ public class Test {
break;
}
switch(thing) {
case B(_, _):
case Integer _, String _, A(_, _) when thing.toString().equals("abc"):
case Float _:
break;
default:
break;
}
var result = switch(thing) {
case B(_, _):
case Integer _, String _, A(_, _) when thing.toString().equals("abc"):
case Float _:
yield 1;
default:
yield 2;
};
switch ((String)thing) {
case "a":
case String _ when ((String)thing).length() == 5:
case "b":
break;
default:
break;
}
// Test the case where a case falls out of a switch block without a break:
switch(thing) {
case String _:
default:
}
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args --release 22
//semmle-extractor-options: --javac-args --release 21

View File

@@ -16,7 +16,7 @@
| Exhaustive.java:5:15:5:15 | { ... } | Exhaustive.java:5:15:5:15 | super(...) |
| Exhaustive.java:6:15:6:15 | super(...) | Exhaustive.java:6:15:6:15 | Y |
| Exhaustive.java:6:15:6:15 | { ... } | Exhaustive.java:6:15:6:15 | super(...) |
| Exhaustive.java:8:47:35:3 | { ... } | Exhaustive.java:11:5:11:14 | switch (...) |
| Exhaustive.java:8:47:29:3 | { ... } | Exhaustive.java:11:5:11:14 | switch (...) |
| Exhaustive.java:11:5:11:14 | switch (...) | Exhaustive.java:11:13:11:13 | o |
| Exhaustive.java:11:13:11:13 | o | Exhaustive.java:12:7:12:22 | case <Pattern> |
| Exhaustive.java:12:7:12:22 | case <Pattern> | Exhaustive.java:12:19:12:19 | s |
@@ -42,20 +42,13 @@
| Exhaustive.java:25:7:25:17 | case <Pattern> | Exhaustive.java:25:14:25:14 | x |
| Exhaustive.java:25:7:25:17 | case <Pattern> | Exhaustive.java:26:7:26:17 | case <Pattern> |
| Exhaustive.java:25:14:25:14 | x | Exhaustive.java:25:19:25:21 | { ... } |
| Exhaustive.java:25:19:25:21 | { ... } | Exhaustive.java:30:5:30:14 | switch (...) |
| Exhaustive.java:25:19:25:21 | { ... } | Exhaustive.java:8:22:8:25 | test |
| Exhaustive.java:26:7:26:17 | case <Pattern> | Exhaustive.java:26:14:26:14 | y |
| Exhaustive.java:26:14:26:14 | y | Exhaustive.java:26:19:26:21 | { ... } |
| Exhaustive.java:26:19:26:21 | { ... } | Exhaustive.java:30:5:30:14 | switch (...) |
| Exhaustive.java:30:5:30:14 | switch (...) | Exhaustive.java:30:13:30:13 | i |
| Exhaustive.java:30:13:30:13 | i | Exhaustive.java:31:7:31:15 | case <Pattern> |
| Exhaustive.java:31:7:31:15 | case <Pattern> | Exhaustive.java:31:14:31:14 | <anonymous local variable> |
| Exhaustive.java:31:7:31:15 | case <Pattern> | Exhaustive.java:32:7:32:15 | case <Pattern> |
| Exhaustive.java:31:14:31:14 | <anonymous local variable> | Exhaustive.java:8:22:8:25 | test |
| Exhaustive.java:32:7:32:15 | case <Pattern> | Exhaustive.java:32:14:32:14 | <anonymous local variable> |
| Exhaustive.java:32:14:32:14 | <anonymous local variable> | Exhaustive.java:8:22:8:25 | test |
| Exhaustive.java:26:19:26:21 | { ... } | Exhaustive.java:8:22:8:25 | test |
| Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Test |
| Test.java:1:14:1:17 | { ... } | Test.java:1:14:1:17 | super(...) |
| Test.java:3:41:134:3 | { ... } | Test.java:5:6:5:19 | switch (...) |
| Test.java:3:41:101:3 | { ... } | Test.java:5:6:5:19 | switch (...) |
| Test.java:5:6:5:19 | switch (...) | Test.java:5:14:5:18 | thing |
| Test.java:5:14:5:18 | thing | Test.java:6:8:6:23 | case <Pattern> |
| Test.java:6:8:6:23 | case <Pattern> | Test.java:6:20:6:20 | s |
@@ -295,109 +288,26 @@
| Test.java:95:21:95:21 | x | Test.java:95:28:95:28 | y |
| Test.java:95:28:95:28 | y | Test.java:95:15:95:29 | B(...) |
| Test.java:95:36:95:36 | z | Test.java:95:13:95:37 | A(...) |
| Test.java:96:10:96:15 | break | Test.java:101:6:101:18 | switch (...) |
| Test.java:96:10:96:15 | break | Test.java:3:22:3:25 | test |
| Test.java:97:8:97:15 | default | Test.java:98:10:98:15 | break |
| Test.java:98:10:98:15 | break | Test.java:101:6:101:18 | switch (...) |
| Test.java:101:6:101:18 | switch (...) | Test.java:101:13:101:17 | thing |
| Test.java:101:13:101:17 | thing | Test.java:102:8:102:20 | case <Pattern> |
| Test.java:102:8:102:20 | case <Pattern> | Test.java:102:15:102:15 | <anonymous local variable> |
| Test.java:102:8:102:20 | case <Pattern> | Test.java:103:8:103:77 | case <Pattern> |
| Test.java:102:13:102:19 | B(...) | Test.java:105:10:105:15 | break |
| Test.java:102:15:102:15 | <anonymous local variable> | Test.java:102:18:102:18 | <anonymous local variable> |
| Test.java:102:18:102:18 | <anonymous local variable> | Test.java:102:13:102:19 | B(...) |
| Test.java:103:8:103:77 | case <Pattern> | Test.java:103:21:103:21 | <anonymous local variable> |
| Test.java:103:8:103:77 | case <Pattern> | Test.java:103:31:103:31 | <anonymous local variable> |
| Test.java:103:8:103:77 | case <Pattern> | Test.java:103:36:103:36 | <anonymous local variable> |
| Test.java:103:8:103:77 | case <Pattern> | Test.java:104:8:104:20 | case <Pattern> |
| Test.java:103:21:103:21 | <anonymous local variable> | Test.java:103:47:103:51 | thing |
| Test.java:103:31:103:31 | <anonymous local variable> | Test.java:103:47:103:51 | thing |
| Test.java:103:34:103:40 | A(...) | Test.java:103:47:103:51 | thing |
| Test.java:103:36:103:36 | <anonymous local variable> | Test.java:103:39:103:39 | <anonymous local variable> |
| Test.java:103:39:103:39 | <anonymous local variable> | Test.java:103:34:103:40 | A(...) |
| Test.java:103:47:103:51 | thing | Test.java:103:47:103:62 | toString(...) |
| Test.java:103:47:103:62 | toString(...) | Test.java:103:71:103:75 | "abc" |
| Test.java:103:47:103:76 | equals(...) | Test.java:104:8:104:20 | case <Pattern> |
| Test.java:103:47:103:76 | equals(...) | Test.java:105:10:105:15 | break |
| Test.java:103:71:103:75 | "abc" | Test.java:103:47:103:76 | equals(...) |
| Test.java:104:8:104:20 | case <Pattern> | Test.java:104:19:104:19 | <anonymous local variable> |
| Test.java:104:8:104:20 | case <Pattern> | Test.java:106:8:106:15 | default |
| Test.java:104:19:104:19 | <anonymous local variable> | Test.java:105:10:105:15 | break |
| Test.java:105:10:105:15 | break | Test.java:110:6:117:7 | var ...; |
| Test.java:106:8:106:15 | default | Test.java:107:10:107:15 | break |
| Test.java:107:10:107:15 | break | Test.java:110:6:117:7 | var ...; |
| Test.java:110:6:117:7 | var ...; | Test.java:110:19:110:31 | switch (...) |
| Test.java:110:10:110:31 | result | Test.java:119:6:119:27 | switch (...) |
| Test.java:110:19:110:31 | switch (...) | Test.java:110:26:110:30 | thing |
| Test.java:110:26:110:30 | thing | Test.java:111:8:111:20 | case <Pattern> |
| Test.java:111:8:111:20 | case <Pattern> | Test.java:111:15:111:15 | <anonymous local variable> |
| Test.java:111:8:111:20 | case <Pattern> | Test.java:112:8:112:77 | case <Pattern> |
| Test.java:111:13:111:19 | B(...) | Test.java:114:10:114:17 | yield ... |
| Test.java:111:15:111:15 | <anonymous local variable> | Test.java:111:18:111:18 | <anonymous local variable> |
| Test.java:111:18:111:18 | <anonymous local variable> | Test.java:111:13:111:19 | B(...) |
| Test.java:112:8:112:77 | case <Pattern> | Test.java:112:21:112:21 | <anonymous local variable> |
| Test.java:112:8:112:77 | case <Pattern> | Test.java:112:31:112:31 | <anonymous local variable> |
| Test.java:112:8:112:77 | case <Pattern> | Test.java:112:36:112:36 | <anonymous local variable> |
| Test.java:112:8:112:77 | case <Pattern> | Test.java:113:8:113:20 | case <Pattern> |
| Test.java:112:21:112:21 | <anonymous local variable> | Test.java:112:47:112:51 | thing |
| Test.java:112:31:112:31 | <anonymous local variable> | Test.java:112:47:112:51 | thing |
| Test.java:112:34:112:40 | A(...) | Test.java:112:47:112:51 | thing |
| Test.java:112:36:112:36 | <anonymous local variable> | Test.java:112:39:112:39 | <anonymous local variable> |
| Test.java:112:39:112:39 | <anonymous local variable> | Test.java:112:34:112:40 | A(...) |
| Test.java:112:47:112:51 | thing | Test.java:112:47:112:62 | toString(...) |
| Test.java:112:47:112:62 | toString(...) | Test.java:112:71:112:75 | "abc" |
| Test.java:112:47:112:76 | equals(...) | Test.java:113:8:113:20 | case <Pattern> |
| Test.java:112:47:112:76 | equals(...) | Test.java:114:10:114:17 | yield ... |
| Test.java:112:71:112:75 | "abc" | Test.java:112:47:112:76 | equals(...) |
| Test.java:113:8:113:20 | case <Pattern> | Test.java:113:19:113:19 | <anonymous local variable> |
| Test.java:113:8:113:20 | case <Pattern> | Test.java:115:8:115:15 | default |
| Test.java:113:19:113:19 | <anonymous local variable> | Test.java:114:10:114:17 | yield ... |
| Test.java:114:10:114:17 | yield ... | Test.java:114:16:114:16 | 1 |
| Test.java:114:16:114:16 | 1 | Test.java:110:10:110:31 | result |
| Test.java:115:8:115:15 | default | Test.java:116:10:116:17 | yield ... |
| Test.java:116:10:116:17 | yield ... | Test.java:116:16:116:16 | 2 |
| Test.java:116:16:116:16 | 2 | Test.java:110:10:110:31 | result |
| Test.java:119:6:119:27 | switch (...) | Test.java:119:22:119:26 | thing |
| Test.java:119:14:119:26 | (...)... | Test.java:120:8:120:16 | case ... |
| Test.java:119:14:119:26 | (...)... | Test.java:121:8:121:56 | case <Pattern> |
| Test.java:119:22:119:26 | thing | Test.java:119:14:119:26 | (...)... |
| Test.java:120:8:120:16 | case ... | Test.java:122:8:122:16 | case ... |
| Test.java:121:8:121:56 | case <Pattern> | Test.java:121:20:121:20 | <anonymous local variable> |
| Test.java:121:8:121:56 | case <Pattern> | Test.java:122:8:122:16 | case ... |
| Test.java:121:8:121:56 | case <Pattern> | Test.java:124:8:124:15 | default |
| Test.java:121:20:121:20 | <anonymous local variable> | Test.java:121:36:121:40 | thing |
| Test.java:121:27:121:50 | length(...) | Test.java:121:55:121:55 | 5 |
| Test.java:121:27:121:55 | ... == ... | Test.java:122:8:122:16 | case ... |
| Test.java:121:27:121:55 | ... == ... | Test.java:124:8:124:15 | default |
| Test.java:121:28:121:40 | (...)... | Test.java:121:27:121:50 | length(...) |
| Test.java:121:36:121:40 | thing | Test.java:121:28:121:40 | (...)... |
| Test.java:121:55:121:55 | 5 | Test.java:121:27:121:55 | ... == ... |
| Test.java:122:8:122:16 | case ... | Test.java:123:10:123:15 | break |
| Test.java:123:10:123:15 | break | Test.java:129:6:129:18 | switch (...) |
| Test.java:124:8:124:15 | default | Test.java:125:10:125:15 | break |
| Test.java:125:10:125:15 | break | Test.java:129:6:129:18 | switch (...) |
| Test.java:129:6:129:18 | switch (...) | Test.java:129:13:129:17 | thing |
| Test.java:129:13:129:17 | thing | Test.java:130:8:130:21 | case <Pattern> |
| Test.java:130:8:130:21 | case <Pattern> | Test.java:130:20:130:20 | <anonymous local variable> |
| Test.java:130:8:130:21 | case <Pattern> | Test.java:131:8:131:15 | default |
| Test.java:130:20:130:20 | <anonymous local variable> | Test.java:131:8:131:15 | default |
| Test.java:131:8:131:15 | default | Test.java:3:22:3:25 | test |
| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | <Expr>; |
| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | A |
| Test.java:138:8:138:8 | <Expr>; | Test.java:138:8:138:8 | this |
| Test.java:138:8:138:8 | <Expr>; | Test.java:138:8:138:8 | this |
| Test.java:138:8:138:8 | b | Test.java:138:8:138:8 | ...=... |
| Test.java:138:8:138:8 | field3 | Test.java:138:8:138:8 | ...=... |
| Test.java:138:8:138:8 | super(...) | Test.java:138:8:138:8 | <Expr>; |
| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | b |
| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | field3 |
| Test.java:138:8:138:8 | { ... } | Test.java:138:8:138:8 | super(...) |
| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | <Expr>; |
| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | B |
| Test.java:139:8:139:8 | <Expr>; | Test.java:139:8:139:8 | this |
| Test.java:139:8:139:8 | <Expr>; | Test.java:139:8:139:8 | this |
| Test.java:139:8:139:8 | field1 | Test.java:139:8:139:8 | ...=... |
| Test.java:139:8:139:8 | field2 | Test.java:139:8:139:8 | ...=... |
| Test.java:139:8:139:8 | super(...) | Test.java:139:8:139:8 | <Expr>; |
| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | field1 |
| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | field2 |
| Test.java:139:8:139:8 | { ... } | Test.java:139:8:139:8 | super(...) |
| Test.java:98:10:98:15 | break | Test.java:3:22:3:25 | test |
| Test.java:105:8:105:8 | ...=... | Test.java:105:8:105:8 | <Expr>; |
| Test.java:105:8:105:8 | ...=... | Test.java:105:8:105:8 | A |
| Test.java:105:8:105:8 | <Expr>; | Test.java:105:8:105:8 | this |
| Test.java:105:8:105:8 | <Expr>; | Test.java:105:8:105:8 | this |
| Test.java:105:8:105:8 | b | Test.java:105:8:105:8 | ...=... |
| Test.java:105:8:105:8 | field3 | Test.java:105:8:105:8 | ...=... |
| Test.java:105:8:105:8 | super(...) | Test.java:105:8:105:8 | <Expr>; |
| Test.java:105:8:105:8 | this | Test.java:105:8:105:8 | b |
| Test.java:105:8:105:8 | this | Test.java:105:8:105:8 | field3 |
| Test.java:105:8:105:8 | { ... } | Test.java:105:8:105:8 | super(...) |
| Test.java:106:8:106:8 | ...=... | Test.java:106:8:106:8 | <Expr>; |
| Test.java:106:8:106:8 | ...=... | Test.java:106:8:106:8 | B |
| Test.java:106:8:106:8 | <Expr>; | Test.java:106:8:106:8 | this |
| Test.java:106:8:106:8 | <Expr>; | Test.java:106:8:106:8 | this |
| Test.java:106:8:106:8 | field1 | Test.java:106:8:106:8 | ...=... |
| Test.java:106:8:106:8 | field2 | Test.java:106:8:106:8 | ...=... |
| Test.java:106:8:106:8 | super(...) | Test.java:106:8:106:8 | <Expr>; |
| Test.java:106:8:106:8 | this | Test.java:106:8:106:8 | field1 |
| Test.java:106:8:106:8 | this | Test.java:106:8:106:8 | field2 |
| Test.java:106:8:106:8 | { ... } | Test.java:106:8:106:8 | super(...) |

View File

@@ -45,13 +45,6 @@ public class Test {
if (o instanceof R(S(var x), var y)) { }
switch(o) {
case String _, Integer _:
case R(S(_), _):
default:
break;
}
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args --release 22
//semmle-extractor-options: --javac-args --release 21

View File

@@ -84,11 +84,5 @@
| Test.java:1:14:1:17 | Test | 83 | } |
| Test.java:1:14:1:17 | Test | 84 | if (o instanceof R(S(var x), var y)) { |
| Test.java:1:14:1:17 | Test | 85 | } |
| Test.java:1:14:1:17 | Test | 86 | switch (o) { |
| Test.java:1:14:1:17 | Test | 87 | case String _, Integer _: |
| Test.java:1:14:1:17 | Test | 88 | case R(S(var _), var _): |
| Test.java:1:14:1:17 | Test | 89 | default: |
| Test.java:1:14:1:17 | Test | 90 | break; |
| Test.java:1:14:1:17 | Test | 91 | } |
| Test.java:1:14:1:17 | Test | 92 | } |
| Test.java:1:14:1:17 | Test | 93 | } |
| Test.java:1:14:1:17 | Test | 86 | } |
| Test.java:1:14:1:17 | Test | 87 | } |

View File

@@ -1,181 +0,0 @@
import java.io.Closeable;
import java.util.List;
import java.util.function.BiFunction;
record SubRecord(int z) { }
record MyRecord(int x, SubRecord y) { }
public class AnonDecls {
public static void test(List<String> ss, Object o) {
// Note each construct is repeated to ensure this doesn't produce database inconsistencies
int _ = 1;
int _ = 2;
try (Closeable _ = null) { } catch (Exception _) { }
try (Closeable _ = null) { } catch (Exception _) { }
int x = 0;
for (int _ = 1; x < 10; x++) { }
for (int _ = 2; x > 0; x--) { }
for (var _ : ss) { }
for (var _ : ss) { }
BiFunction<Integer, Integer, Integer> f1 = (_, _) -> 1;
BiFunction<Integer, Integer, Integer> f2 = (_, _) -> 2;
switch (o) {
case SubRecord _:
case MyRecord _:
default:
}
switch (o) {
case SubRecord _:
case MyRecord (int _, SubRecord _):
default:
}
switch (o) {
case SubRecord _:
case MyRecord (int _, SubRecord (int _)):
default:
}
switch (o) {
case SubRecord _:
case MyRecord (_, _):
default:
}
switch (o) {
case MyRecord (_, _), SubRecord(_):
default:
}
switch (o) {
case MyRecord (_, _), SubRecord(_) when ss != null:
default:
}
switch (o) {
// Note use of binding patterns, not records with unnamed patterns as above
case MyRecord _, SubRecord _:
default:
}
switch (o) {
case SubRecord _ -> { }
case MyRecord _ -> { }
default -> { }
}
switch (o) {
case SubRecord _ -> { }
case MyRecord (int _, SubRecord _) -> { }
default -> { }
}
switch (o) {
case SubRecord _ -> { }
case MyRecord (int _, SubRecord (int _)) -> { }
default -> { }
}
switch (o) {
case SubRecord _ -> { }
case MyRecord (_, _) -> { }
default -> { }
}
switch (o) {
case MyRecord (_, _), SubRecord(_) -> { }
default -> { }
}
switch (o) {
case MyRecord (_, _), SubRecord(_) when ss != null -> { }
default -> { }
}
var x1 = switch (o) {
case SubRecord _:
case MyRecord _:
default:
yield 1;
};
var x2 = switch (o) {
case SubRecord _:
case MyRecord (int _, SubRecord _):
default:
yield 1;
};
var x3 = switch (o) {
case SubRecord _:
case MyRecord (int _, SubRecord (int _)):
default:
yield 1;
};
var x4 = switch (o) {
case SubRecord _:
case MyRecord (_, _):
default:
yield 1;
};
var x5 = switch (o) {
case MyRecord (_, _), SubRecord(_):
default:
yield 1;
};
var x6 = switch (o) {
case MyRecord (_, _), SubRecord(_) when ss != null:
default:
yield 1;
};
var x7 = switch (o) {
case SubRecord _ -> 1;
case MyRecord _ -> 2;
default -> 3;
};
var x8 = switch (o) {
case SubRecord _ -> 1;
case MyRecord (int _, SubRecord _) -> 2;
default -> 3;
};
var x9 = switch (o) {
case SubRecord _ -> 1;
case MyRecord (int _, SubRecord (int _)) -> 2;
default -> 3;
};
var x10 = switch (o) {
case SubRecord _ -> 1;
case MyRecord (_, _) -> 2;
default -> 3;
};
var x11 = switch (o) {
case MyRecord (_, _), SubRecord(_) -> 1;
default -> 2;
};
var x12 = switch (o) {
case MyRecord (_, _), SubRecord(_) when ss != null -> 1;
default -> 2;
};
}
}

View File

@@ -127,7 +127,7 @@ A.java:
# 54| -1: [VarAccess] System.out
# 54| -1: [TypeAccess] System
# 54| 0: [VarAccess] s
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 54| 0: [TypeAccess] String
# 54| 1: [LocalVariableDeclExpr] s
# 55| 1: [PatternCase] case <Pattern>
@@ -138,7 +138,7 @@ A.java:
# 55| 0: [AddExpr] ... + ...
# 55| 0: [StringLiteral] "An integer: "
# 55| 1: [VarAccess] i
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 55| 0: [TypeAccess] Integer
# 55| 1: [LocalVariableDeclExpr] i
# 56| 2: [DefaultCase] default
@@ -146,7 +146,7 @@ A.java:
# 58| 3: [SwitchStmt] switch (...)
# 58| -1: [VarAccess] thing
# 59| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 59| 0: [TypeAccess] String
# 59| 1: [LocalVariableDeclExpr] s
# 60| 1: [ExprStmt] <Expr>;
@@ -156,7 +156,7 @@ A.java:
# 60| 0: [VarAccess] s
# 61| 2: [BreakStmt] break
# 62| 3: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 62| 0: [TypeAccess] Integer
# 62| 1: [LocalVariableDeclExpr] i
# 63| 4: [ExprStmt] <Expr>;
@@ -175,14 +175,14 @@ A.java:
# 68| -1: [VarAccess] thing
# 69| 0: [PatternCase] case <Pattern>
# 69| -1: [VarAccess] s
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 69| 0: [TypeAccess] String
# 69| 1: [LocalVariableDeclExpr] s
# 70| 1: [PatternCase] case <Pattern>
# 70| -1: [AddExpr] ... + ...
# 70| 0: [StringLiteral] "An integer: "
# 70| 1: [VarAccess] i
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 70| 0: [TypeAccess] Integer
# 70| 1: [LocalVariableDeclExpr] i
# 71| 2: [DefaultCase] default
@@ -192,13 +192,13 @@ A.java:
# 73| 0: [SwitchExpr] switch (...)
# 73| -1: [VarAccess] thing
# 74| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 74| 0: [TypeAccess] String
# 74| 1: [LocalVariableDeclExpr] s
# 75| 1: [YieldStmt] yield ...
# 75| 0: [VarAccess] s
# 76| 2: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 76| 0: [TypeAccess] Integer
# 76| 1: [LocalVariableDeclExpr] i
# 77| 3: [YieldStmt] yield ...
@@ -232,7 +232,7 @@ A.java:
# 87| -1: [VarAccess] s
# 87| 1: [IntegerLiteral] 3
# 87| -1: [StringLiteral] "It's 3 letters long"
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 87| 0: [TypeAccess] String
# 87| 1: [LocalVariableDeclExpr] s
# 88| 2: [PatternCase] case <Pattern>
@@ -241,7 +241,7 @@ A.java:
# 88| -1: [VarAccess] s
# 88| 1: [IntegerLiteral] 5
# 88| -1: [StringLiteral] "it's 5 letters long"
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 88| 0: [TypeAccess] String
# 88| 1: [LocalVariableDeclExpr] s
# 89| 3: [DefaultCase] default
@@ -252,7 +252,7 @@ A.java:
# 91| -1: [VarAccess] thing
# 92| 0: [PatternCase] case <Pattern>
# 92| -1: [StringLiteral] "It's a string"
#-----| 0: (Pattern case declaration)
#-----| 0: (Single Local Variable Declaration)
# 92| 0: [TypeAccess] String
# 92| 1: [LocalVariableDeclExpr] s
# 93| 1: [NullDefaultCase] case null, default
@@ -332,486 +332,3 @@ A.java:
# 130| 2: [FieldDeclaration] String field;
# 131| 3: [Class] Middle
# 131| 2: [FieldDeclaration] Inner inner;
AnonDecls.java:
# 0| [CompilationUnit] AnonDecls
#-----| -1: (Imports)
# 1| 1: [ImportType] import Closeable
# 2| 2: [ImportType] import List
# 3| 3: [ImportType] import BiFunction
# 5| 1: [Class] SubRecord
# 5| 2: [FieldDeclaration] int z;
# 6| 2: [Class] MyRecord
# 6| 2: [FieldDeclaration] int x;
# 6| 3: [FieldDeclaration] SubRecord y;
# 8| 3: [Class] AnonDecls
# 10| 2: [Method] test
# 10| 3: [TypeAccess] void
#-----| 4: (Parameters)
# 10| 0: [Parameter] ss
# 10| 0: [TypeAccess] List<String>
# 10| 0: [TypeAccess] String
# 10| 1: [Parameter] o
# 10| 0: [TypeAccess] Object
# 10| 5: [BlockStmt] { ... }
# 14| 0: [LocalVariableDeclStmt] var ...;
# 14| 0: [TypeAccess] int
# 14| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 14| 0: [IntegerLiteral] 1
# 15| 1: [LocalVariableDeclStmt] var ...;
# 15| 0: [TypeAccess] int
# 15| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 15| 0: [IntegerLiteral] 2
# 17| 2: [TryStmt] try ...
# 17| -3: [LocalVariableDeclStmt] var ...;
# 17| 0: [TypeAccess] Closeable
# 17| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 17| 0: [NullLiteral] null
# 17| -1: [BlockStmt] { ... }
# 17| 0: [CatchClause] catch (...)
#-----| 0: (Single Local Variable Declaration)
# 17| 0: [TypeAccess] Exception
# 17| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 17| 1: [BlockStmt] { ... }
# 18| 3: [TryStmt] try ...
# 18| -3: [LocalVariableDeclStmt] var ...;
# 18| 0: [TypeAccess] Closeable
# 18| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 18| 0: [NullLiteral] null
# 18| -1: [BlockStmt] { ... }
# 18| 0: [CatchClause] catch (...)
#-----| 0: (Single Local Variable Declaration)
# 18| 0: [TypeAccess] Exception
# 18| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 18| 1: [BlockStmt] { ... }
# 20| 4: [LocalVariableDeclStmt] var ...;
# 20| 0: [TypeAccess] int
# 20| 1: [LocalVariableDeclExpr] x
# 20| 0: [IntegerLiteral] 0
# 22| 5: [ForStmt] for (...;...;...)
#-----| 0: (For Initializers)
# 22| 0: [TypeAccess] int
# 22| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 22| 0: [IntegerLiteral] 1
# 22| 1: [LTExpr] ... < ...
# 22| 0: [VarAccess] x
# 22| 1: [IntegerLiteral] 10
# 22| 2: [BlockStmt] { ... }
# 22| 3: [PostIncExpr] ...++
# 22| 0: [VarAccess] x
# 23| 6: [ForStmt] for (...;...;...)
#-----| 0: (For Initializers)
# 23| 0: [TypeAccess] int
# 23| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 23| 0: [IntegerLiteral] 2
# 23| 1: [GTExpr] ... > ...
# 23| 0: [VarAccess] x
# 23| 1: [IntegerLiteral] 0
# 23| 2: [BlockStmt] { ... }
# 23| 3: [PostDecExpr] ...--
# 23| 0: [VarAccess] x
# 25| 7: [EnhancedForStmt] for (... : ...)
#-----| 0: (Single Local Variable Declaration)
# 25| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 25| 1: [VarAccess] ss
# 25| 2: [BlockStmt] { ... }
# 26| 8: [EnhancedForStmt] for (... : ...)
#-----| 0: (Single Local Variable Declaration)
# 26| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 26| 1: [VarAccess] ss
# 26| 2: [BlockStmt] { ... }
# 28| 9: [LocalVariableDeclStmt] var ...;
# 28| 0: [TypeAccess] BiFunction<Integer,Integer,Integer>
# 28| 0: [TypeAccess] Integer
# 28| 1: [TypeAccess] Integer
# 28| 2: [TypeAccess] Integer
# 28| 1: [LocalVariableDeclExpr] f1
# 28| 0: [LambdaExpr] ...->...
# 28| -4: [AnonymousClass] new BiFunction<Integer,Integer,Integer>(...) { ... }
# 28| 2: [Method] apply
#-----| 4: (Parameters)
# 28| 0: [Parameter] <anonymous parameter>
# 28| 1: [Parameter] <anonymous parameter>
# 28| 5: [BlockStmt] { ... }
# 28| 0: [ReturnStmt] return ...
# 28| 0: [IntegerLiteral] 1
# 28| -3: [TypeAccess] BiFunction<Integer,Integer,Integer>
# 28| 0: [TypeAccess] Integer
# 28| 1: [TypeAccess] Integer
# 28| 2: [TypeAccess] Integer
# 29| 10: [LocalVariableDeclStmt] var ...;
# 29| 0: [TypeAccess] BiFunction<Integer,Integer,Integer>
# 29| 0: [TypeAccess] Integer
# 29| 1: [TypeAccess] Integer
# 29| 2: [TypeAccess] Integer
# 29| 1: [LocalVariableDeclExpr] f2
# 29| 0: [LambdaExpr] ...->...
# 29| -4: [AnonymousClass] new BiFunction<Integer,Integer,Integer>(...) { ... }
# 29| 2: [Method] apply
#-----| 4: (Parameters)
# 29| 0: [Parameter] <anonymous parameter>
# 29| 1: [Parameter] <anonymous parameter>
# 29| 5: [BlockStmt] { ... }
# 29| 0: [ReturnStmt] return ...
# 29| 0: [IntegerLiteral] 2
# 29| -3: [TypeAccess] BiFunction<Integer,Integer,Integer>
# 29| 0: [TypeAccess] Integer
# 29| 1: [TypeAccess] Integer
# 29| 2: [TypeAccess] Integer
# 31| 11: [SwitchStmt] switch (...)
# 31| -1: [VarAccess] o
# 32| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 32| 0: [TypeAccess] SubRecord
# 32| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 33| 1: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 33| 0: [TypeAccess] MyRecord
# 33| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 34| 2: [DefaultCase] default
# 37| 12: [SwitchStmt] switch (...)
# 37| -1: [VarAccess] o
# 38| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 38| 0: [TypeAccess] SubRecord
# 38| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 39| 1: [PatternCase] case <Pattern>
# 39| 0: [RecordPatternExpr] MyRecord(...)
# 39| -2: [TypeAccess] SubRecord
# 39| -1: [TypeAccess] int
# 39| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 39| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 40| 2: [DefaultCase] default
# 43| 13: [SwitchStmt] switch (...)
# 43| -1: [VarAccess] o
# 44| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 44| 0: [TypeAccess] SubRecord
# 44| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 45| 1: [PatternCase] case <Pattern>
# 45| 0: [RecordPatternExpr] MyRecord(...)
# 45| -1: [TypeAccess] int
# 45| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 45| 1: [RecordPatternExpr] SubRecord(...)
# 45| -1: [TypeAccess] int
# 45| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 46| 2: [DefaultCase] default
# 49| 14: [SwitchStmt] switch (...)
# 49| -1: [VarAccess] o
# 50| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 50| 0: [TypeAccess] SubRecord
# 50| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 51| 1: [PatternCase] case <Pattern>
# 51| 0: [RecordPatternExpr] MyRecord(...)
# 51| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 51| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 52| 2: [DefaultCase] default
# 55| 15: [SwitchStmt] switch (...)
# 55| -1: [VarAccess] o
# 56| 0: [PatternCase] case <Pattern>
# 56| 0: [RecordPatternExpr] MyRecord(...)
# 56| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 56| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 56| 1: [RecordPatternExpr] SubRecord(...)
# 56| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 57| 1: [DefaultCase] default
# 60| 16: [SwitchStmt] switch (...)
# 60| -1: [VarAccess] o
# 61| 0: [PatternCase] case <Pattern>
# 61| -3: [NEExpr] ... != ...
# 61| 0: [VarAccess] ss
# 61| 1: [NullLiteral] null
# 61| 0: [RecordPatternExpr] MyRecord(...)
# 61| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 61| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 61| 1: [RecordPatternExpr] SubRecord(...)
# 61| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 62| 1: [DefaultCase] default
# 65| 17: [SwitchStmt] switch (...)
# 65| -1: [VarAccess] o
# 67| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 67| 0: [TypeAccess] MyRecord
# 67| 1: [LocalVariableDeclExpr] <anonymous local variable>
#-----| 1: (Pattern case declaration)
# 67| 0: [TypeAccess] SubRecord
# 67| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 68| 1: [DefaultCase] default
# 71| 18: [SwitchStmt] switch (...)
# 71| -1: [VarAccess] o
# 72| 0: [PatternCase] case <Pattern>
# 72| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
# 72| 0: [TypeAccess] SubRecord
# 72| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 73| 1: [PatternCase] case <Pattern>
# 73| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
# 73| 0: [TypeAccess] MyRecord
# 73| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 74| 2: [DefaultCase] default
# 74| -1: [BlockStmt] { ... }
# 77| 19: [SwitchStmt] switch (...)
# 77| -1: [VarAccess] o
# 78| 0: [PatternCase] case <Pattern>
# 78| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
# 78| 0: [TypeAccess] SubRecord
# 78| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 79| 1: [PatternCase] case <Pattern>
# 79| -1: [BlockStmt] { ... }
# 79| 0: [RecordPatternExpr] MyRecord(...)
# 79| -2: [TypeAccess] SubRecord
# 79| -1: [TypeAccess] int
# 79| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 79| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 80| 2: [DefaultCase] default
# 80| -1: [BlockStmt] { ... }
# 83| 20: [SwitchStmt] switch (...)
# 83| -1: [VarAccess] o
# 84| 0: [PatternCase] case <Pattern>
# 84| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
# 84| 0: [TypeAccess] SubRecord
# 84| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 85| 1: [PatternCase] case <Pattern>
# 85| -1: [BlockStmt] { ... }
# 85| 0: [RecordPatternExpr] MyRecord(...)
# 85| -1: [TypeAccess] int
# 85| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 85| 1: [RecordPatternExpr] SubRecord(...)
# 85| -1: [TypeAccess] int
# 85| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 86| 2: [DefaultCase] default
# 86| -1: [BlockStmt] { ... }
# 89| 21: [SwitchStmt] switch (...)
# 89| -1: [VarAccess] o
# 90| 0: [PatternCase] case <Pattern>
# 90| -1: [BlockStmt] { ... }
#-----| 0: (Pattern case declaration)
# 90| 0: [TypeAccess] SubRecord
# 90| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 91| 1: [PatternCase] case <Pattern>
# 91| -1: [BlockStmt] { ... }
# 91| 0: [RecordPatternExpr] MyRecord(...)
# 91| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 91| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 92| 2: [DefaultCase] default
# 92| -1: [BlockStmt] { ... }
# 95| 22: [SwitchStmt] switch (...)
# 95| -1: [VarAccess] o
# 96| 0: [PatternCase] case <Pattern>
# 96| -1: [BlockStmt] { ... }
# 96| 0: [RecordPatternExpr] MyRecord(...)
# 96| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 96| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 96| 1: [RecordPatternExpr] SubRecord(...)
# 96| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 97| 1: [DefaultCase] default
# 97| -1: [BlockStmt] { ... }
# 100| 23: [SwitchStmt] switch (...)
# 100| -1: [VarAccess] o
# 101| 0: [PatternCase] case <Pattern>
# 101| -3: [NEExpr] ... != ...
# 101| 0: [VarAccess] ss
# 101| 1: [NullLiteral] null
# 101| -1: [BlockStmt] { ... }
# 101| 0: [RecordPatternExpr] MyRecord(...)
# 101| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 101| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 101| 1: [RecordPatternExpr] SubRecord(...)
# 101| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 102| 1: [DefaultCase] default
# 102| -1: [BlockStmt] { ... }
# 105| 24: [LocalVariableDeclStmt] var ...;
# 105| 1: [LocalVariableDeclExpr] x1
# 105| 0: [SwitchExpr] switch (...)
# 105| -1: [VarAccess] o
# 106| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 106| 0: [TypeAccess] SubRecord
# 106| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 107| 1: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 107| 0: [TypeAccess] MyRecord
# 107| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 108| 2: [DefaultCase] default
# 109| 3: [YieldStmt] yield ...
# 109| 0: [IntegerLiteral] 1
# 112| 25: [LocalVariableDeclStmt] var ...;
# 112| 1: [LocalVariableDeclExpr] x2
# 112| 0: [SwitchExpr] switch (...)
# 112| -1: [VarAccess] o
# 113| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 113| 0: [TypeAccess] SubRecord
# 113| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 114| 1: [PatternCase] case <Pattern>
# 114| 0: [RecordPatternExpr] MyRecord(...)
# 114| -2: [TypeAccess] SubRecord
# 114| -1: [TypeAccess] int
# 114| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 114| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 115| 2: [DefaultCase] default
# 116| 3: [YieldStmt] yield ...
# 116| 0: [IntegerLiteral] 1
# 119| 26: [LocalVariableDeclStmt] var ...;
# 119| 1: [LocalVariableDeclExpr] x3
# 119| 0: [SwitchExpr] switch (...)
# 119| -1: [VarAccess] o
# 120| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 120| 0: [TypeAccess] SubRecord
# 120| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 121| 1: [PatternCase] case <Pattern>
# 121| 0: [RecordPatternExpr] MyRecord(...)
# 121| -1: [TypeAccess] int
# 121| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 121| 1: [RecordPatternExpr] SubRecord(...)
# 121| -1: [TypeAccess] int
# 121| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 122| 2: [DefaultCase] default
# 123| 3: [YieldStmt] yield ...
# 123| 0: [IntegerLiteral] 1
# 126| 27: [LocalVariableDeclStmt] var ...;
# 126| 1: [LocalVariableDeclExpr] x4
# 126| 0: [SwitchExpr] switch (...)
# 126| -1: [VarAccess] o
# 127| 0: [PatternCase] case <Pattern>
#-----| 0: (Pattern case declaration)
# 127| 0: [TypeAccess] SubRecord
# 127| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 128| 1: [PatternCase] case <Pattern>
# 128| 0: [RecordPatternExpr] MyRecord(...)
# 128| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 128| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 129| 2: [DefaultCase] default
# 130| 3: [YieldStmt] yield ...
# 130| 0: [IntegerLiteral] 1
# 133| 28: [LocalVariableDeclStmt] var ...;
# 133| 1: [LocalVariableDeclExpr] x5
# 133| 0: [SwitchExpr] switch (...)
# 133| -1: [VarAccess] o
# 134| 0: [PatternCase] case <Pattern>
# 134| 0: [RecordPatternExpr] MyRecord(...)
# 134| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 134| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 134| 1: [RecordPatternExpr] SubRecord(...)
# 134| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 135| 1: [DefaultCase] default
# 136| 2: [YieldStmt] yield ...
# 136| 0: [IntegerLiteral] 1
# 139| 29: [LocalVariableDeclStmt] var ...;
# 139| 1: [LocalVariableDeclExpr] x6
# 139| 0: [SwitchExpr] switch (...)
# 139| -1: [VarAccess] o
# 140| 0: [PatternCase] case <Pattern>
# 140| -3: [NEExpr] ... != ...
# 140| 0: [VarAccess] ss
# 140| 1: [NullLiteral] null
# 140| 0: [RecordPatternExpr] MyRecord(...)
# 140| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 140| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 140| 1: [RecordPatternExpr] SubRecord(...)
# 140| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 141| 1: [DefaultCase] default
# 142| 2: [YieldStmt] yield ...
# 142| 0: [IntegerLiteral] 1
# 145| 30: [LocalVariableDeclStmt] var ...;
# 145| 1: [LocalVariableDeclExpr] x7
# 145| 0: [SwitchExpr] switch (...)
# 145| -1: [VarAccess] o
# 146| 0: [PatternCase] case <Pattern>
# 146| -1: [IntegerLiteral] 1
#-----| 0: (Pattern case declaration)
# 146| 0: [TypeAccess] SubRecord
# 146| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 147| 1: [PatternCase] case <Pattern>
# 147| -1: [IntegerLiteral] 2
#-----| 0: (Pattern case declaration)
# 147| 0: [TypeAccess] MyRecord
# 147| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 148| 2: [DefaultCase] default
# 148| -1: [IntegerLiteral] 3
# 151| 31: [LocalVariableDeclStmt] var ...;
# 151| 1: [LocalVariableDeclExpr] x8
# 151| 0: [SwitchExpr] switch (...)
# 151| -1: [VarAccess] o
# 152| 0: [PatternCase] case <Pattern>
# 152| -1: [IntegerLiteral] 1
#-----| 0: (Pattern case declaration)
# 152| 0: [TypeAccess] SubRecord
# 152| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 153| 1: [PatternCase] case <Pattern>
# 153| -1: [IntegerLiteral] 2
# 153| 0: [RecordPatternExpr] MyRecord(...)
# 153| -2: [TypeAccess] SubRecord
# 153| -1: [TypeAccess] int
# 153| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 153| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 154| 2: [DefaultCase] default
# 154| -1: [IntegerLiteral] 3
# 157| 32: [LocalVariableDeclStmt] var ...;
# 157| 1: [LocalVariableDeclExpr] x9
# 157| 0: [SwitchExpr] switch (...)
# 157| -1: [VarAccess] o
# 158| 0: [PatternCase] case <Pattern>
# 158| -1: [IntegerLiteral] 1
#-----| 0: (Pattern case declaration)
# 158| 0: [TypeAccess] SubRecord
# 158| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 159| 1: [PatternCase] case <Pattern>
# 159| -1: [IntegerLiteral] 2
# 159| 0: [RecordPatternExpr] MyRecord(...)
# 159| -1: [TypeAccess] int
# 159| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 159| 1: [RecordPatternExpr] SubRecord(...)
# 159| -1: [TypeAccess] int
# 159| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 160| 2: [DefaultCase] default
# 160| -1: [IntegerLiteral] 3
# 163| 33: [LocalVariableDeclStmt] var ...;
# 163| 1: [LocalVariableDeclExpr] x10
# 163| 0: [SwitchExpr] switch (...)
# 163| -1: [VarAccess] o
# 164| 0: [PatternCase] case <Pattern>
# 164| -1: [IntegerLiteral] 1
#-----| 0: (Pattern case declaration)
# 164| 0: [TypeAccess] SubRecord
# 164| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 165| 1: [PatternCase] case <Pattern>
# 165| -1: [IntegerLiteral] 2
# 165| 0: [RecordPatternExpr] MyRecord(...)
# 165| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 165| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 166| 2: [DefaultCase] default
# 166| -1: [IntegerLiteral] 3
# 169| 34: [LocalVariableDeclStmt] var ...;
# 169| 1: [LocalVariableDeclExpr] x11
# 169| 0: [SwitchExpr] switch (...)
# 169| -1: [VarAccess] o
# 170| 0: [PatternCase] case <Pattern>
# 170| -1: [IntegerLiteral] 1
# 170| 0: [RecordPatternExpr] MyRecord(...)
# 170| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 170| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 170| 1: [RecordPatternExpr] SubRecord(...)
# 170| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 171| 1: [DefaultCase] default
# 171| -1: [IntegerLiteral] 2
# 174| 35: [LocalVariableDeclStmt] var ...;
# 174| 1: [LocalVariableDeclExpr] x12
# 174| 0: [SwitchExpr] switch (...)
# 174| -1: [VarAccess] o
# 175| 0: [PatternCase] case <Pattern>
# 175| -3: [NEExpr] ... != ...
# 175| 0: [VarAccess] ss
# 175| 1: [NullLiteral] null
# 175| -1: [IntegerLiteral] 1
# 175| 0: [RecordPatternExpr] MyRecord(...)
# 175| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 175| 1: [LocalVariableDeclExpr] <anonymous local variable>
# 175| 1: [RecordPatternExpr] SubRecord(...)
# 175| 0: [LocalVariableDeclExpr] <anonymous local variable>
# 176| 1: [DefaultCase] default
# 176| -1: [IntegerLiteral] 2

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args --release 22
//semmle-extractor-options: --javac-args --release 21

View File

@@ -58,31 +58,6 @@ public class Test {
case null: default: i.take(source()); // Can't call C1.take (but we don't currently notice)
}
switch(i) {
case C1 _, C2 _:
i.take(source()); // Must be either C1.take or C2.take (but we don't currently notice, because neither dominates)
break;
default:
i.take(source()); // Can't call C1.take or C2.take (but we don't currently notice, because a multi-pattern case isn't understood as a type test)
}
switch(i) {
case C1 _, C2 _ when i.toString().equals("abc"):
i.take(source()); // Must be either C1.take or C2.take (but we don't currently notice, because neither dominates)
break;
default:
i.take(source()); // Can't call C1.take or C2.take (but we don't currently notice, because a multi-pattern case isn't understood as a type test)
}
switch(i) {
case C1 _:
case C2 _:
i.take(source()); // Must be either C1.take or C2.take (but we don't currently notice, because neither dominates)
break;
default:
i.take(source()); // Can't call C1.take or C2.take
}
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args --release 22
//semmle-extractor-options: --javac-args --release 21

View File

@@ -30,25 +30,3 @@
| Test.java:58:34:58:41 | source(...) | Test.java:8:65:8:65 | x |
| Test.java:58:34:58:41 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:58:34:58:41 | source(...) | Test.java:10:82:10:82 | x |
| Test.java:63:16:63:23 | source(...) | Test.java:7:65:7:65 | x |
| Test.java:63:16:63:23 | source(...) | Test.java:8:65:8:65 | x |
| Test.java:63:16:63:23 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:63:16:63:23 | source(...) | Test.java:10:82:10:82 | x |
| Test.java:66:16:66:23 | source(...) | Test.java:7:65:7:65 | x |
| Test.java:66:16:66:23 | source(...) | Test.java:8:65:8:65 | x |
| Test.java:66:16:66:23 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:66:16:66:23 | source(...) | Test.java:10:82:10:82 | x |
| Test.java:71:16:71:23 | source(...) | Test.java:7:65:7:65 | x |
| Test.java:71:16:71:23 | source(...) | Test.java:8:65:8:65 | x |
| Test.java:71:16:71:23 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:71:16:71:23 | source(...) | Test.java:10:82:10:82 | x |
| Test.java:74:16:74:23 | source(...) | Test.java:7:65:7:65 | x |
| Test.java:74:16:74:23 | source(...) | Test.java:8:65:8:65 | x |
| Test.java:74:16:74:23 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:74:16:74:23 | source(...) | Test.java:10:82:10:82 | x |
| Test.java:80:16:80:23 | source(...) | Test.java:7:65:7:65 | x |
| Test.java:80:16:80:23 | source(...) | Test.java:8:65:8:65 | x |
| Test.java:80:16:80:23 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:80:16:80:23 | source(...) | Test.java:10:82:10:82 | x |
| Test.java:83:16:83:23 | source(...) | Test.java:9:74:9:74 | x |
| Test.java:83:16:83:23 | source(...) | Test.java:10:82:10:82 | x |

View File

@@ -3,7 +3,7 @@ extensions:
pack: codeql/python-all
extensible: summaryModel
data:
- ["foo", "Member[MS_identity]", "Argument[0,x:]", "ReturnValue", "value"]
- ["foo", "Member[MS_identity]", "Argument[0]", "ReturnValue", "value"]
- ["foo", "Member[MS_apply_lambda]", "Argument[1]", "Argument[0].Parameter[0]", "value"]
- ["foo", "Member[MS_apply_lambda]", "Argument[0].ReturnValue", "ReturnValue", "value"]
- ["foo", "Member[MS_reversed]", "Argument[0].ListElement", "ReturnValue.ListElement", "value"]
@@ -17,5 +17,4 @@ extensions:
- ["foo", "Member[MS_append_to_list]", "Argument[1]", "ReturnValue", "taint"]
- ["foo", "Member[MS_spread]", "Argument[0]", "ReturnValue.TupleElement[0]", "value"]
- ["foo", "Member[MS_spread]", "Argument[1]", "ReturnValue.TupleElement[1]", "value"]
- ["foo", "Member[MS_spread_all]", "Argument[0]", "ReturnValue.TupleElement[0,1]", "value"]
- ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"]

View File

@@ -3,7 +3,7 @@ extensions:
pack: codeql/python-all
extensible: summaryModel
data:
- ["foo", "Member[MS_identity]", "Argument[0,x:]", "ReturnValue", "value"]
- ["foo", "Member[MS_identity]", "Argument[0]", "ReturnValue", "value"]
- ["foo", "Member[MS_apply_lambda]", "Argument[1]", "Argument[0].Parameter[0]", "value"]
- ["foo", "Member[MS_apply_lambda]", "Argument[0].ReturnValue", "ReturnValue", "value"]
- ["foo", "Member[MS_reversed]", "Argument[0].ListElement", "ReturnValue.ListElement", "value"]
@@ -17,5 +17,4 @@ extensions:
- ["foo", "Member[MS_append_to_list]", "Argument[1]", "ReturnValue", "taint"]
- ["foo", "Member[MS_spread]", "Argument[0]", "ReturnValue.TupleElement[0]", "value"]
- ["foo", "Member[MS_spread]", "Argument[1]", "ReturnValue.TupleElement[1]", "value"]
- ["foo", "Member[MS_spread_all]", "Argument[0]", "ReturnValue.TupleElement[0,1]", "value"]
- ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"]

View File

@@ -30,16 +30,12 @@ def SINK_F(x):
ensure_tainted = ensure_not_tainted = print
TAINTED_STRING = "TAINTED_STRING"
from foo import MS_identity, MS_apply_lambda, MS_reversed, MS_list_map, MS_append_to_list, MS_spread, MS_spread_all
from foo import MS_identity, MS_apply_lambda, MS_reversed, MS_list_map, MS_append_to_list, MS_spread
# Simple summary
via_identity = MS_identity(SOURCE)
SINK(via_identity) # $ flow="SOURCE, l:-1 -> via_identity"
# Simple summary keyword
via_identity_kw = MS_identity(x = SOURCE)
SINK(via_identity_kw) # $ flow="SOURCE, l:-1 -> via_identity_kw"
# Lambda summary
via_lambda = MS_apply_lambda(lambda x: [x], SOURCE)
SINK(via_lambda[0]) # $ flow="SOURCE, l:-1 -> via_lambda[0]"
@@ -118,10 +114,6 @@ x, y = MS_spread(NONSOURCE, SOURCE)
SINK_F(x)
SINK(y) # $ flow="SOURCE, l:-2 -> y"
a, b = MS_spread_all(SOURCE)
SINK(a) # $ flow="SOURCE, l:-1 -> a"
SINK(b) # $ flow="SOURCE, l:-2 -> b"
# Modeled flow-summary is not value preserving
from json import MS_loads as json_loads

View File

@@ -3749,13 +3749,6 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
private predicate isFlowSource(PathNodeImpl n) { n.isFlowSource() }
private predicate isFlowSink(PathNodeImpl n) { n.isFlowSink() }
private predicate doublyBoundedPathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) =
doublyBoundedFastTC(pathSucc/2, isFlowSource/1, isFlowSink/1)(n1, n2)
/**
* A `Node` augmented with a call context (except for sinks) and an access path.
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
@@ -4444,9 +4437,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
exists(PathNodeImpl flowsource, PathNodeImpl flowsink |
source = flowsource and sink = flowsink
|
flowsource.isFlowSource() and flowsink.isFlowSink() and flowsource = flowsink
or
doublyBoundedPathSuccPlus(flowsource, flowsink)
flowsource.isFlowSource() and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.isFlowSink()
)
}

View File

@@ -1 +1 @@
3.11
3.8.14

View File

@@ -18,7 +18,7 @@ runs:
- name: Run integration tests
shell: bash
run: |
python swift/ql/integration-tests/runner.py --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
python swift/integration-tests/runner.py --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
SEMMLE_DEBUG_TRACER: 10000
- name: Upload test logs
@@ -27,5 +27,5 @@ runs:
with:
name: swift-integration-tests-logs-${{ runner.os }}
path: |
swift/ql/integration-tests/**/db/log
swift/integration-tests/**/db/log
retention-days: 1

View File

@@ -6,5 +6,5 @@ xcuserdata/
DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
*.actual
test-db
db
*.swiftmodule

View File

@@ -1,5 +1,5 @@
py_library(
name = "utils",
name = "integration_tests",
srcs = [
"create_database_utils.py",
"diagnostics_test_utils.py",

View File

@@ -27,8 +27,8 @@ def runUnsuccessfully(cmd):
def run_codeql_database_create(cmds, lang, keep_trap=True, db=None, runFunction=runSuccessfully):
""" db parameter is here solely for compatibility with the internal test runner """
assert lang == 'swift'
codeql_root = pathlib.Path(__file__).parents[3]
shutil.rmtree("test-db", ignore_errors=True)
codeql_root = pathlib.Path(__file__).parents[2]
shutil.rmtree("db", ignore_errors=True)
cmd = [
"codeql", "database", "create",
"-s", ".", "-l", "swift", f"--search-path={codeql_root}", "--no-cleanup",
@@ -37,5 +37,5 @@ def run_codeql_database_create(cmds, lang, keep_trap=True, db=None, runFunction=
cmd.append("--keep-trap")
for c in cmds:
cmd += ["-c", c]
cmd.append("test-db")
cmd.append("db")
runFunction(cmd)

View File

@@ -50,7 +50,7 @@ def _normalize_json(data):
return "\n".join(entries)
def check_diagnostics(test_dir=".", test_db="test-db", actual = None):
def check_diagnostics(test_dir=".", test_db="db", actual = None):
test_dir = pathlib.Path(test_dir)
test_db = pathlib.Path(test_db)
if actual is None:

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