Skip to content

Comments

Merge upstream codeql-cli/latest.#331

Merged
dilanbhalla merged 541 commits intomainfrom
jb1/merge-upstream-latest
Feb 23, 2026
Merged

Merge upstream codeql-cli/latest.#331
dilanbhalla merged 541 commits intomainfrom
jb1/merge-upstream-latest

Conversation

@ropwareJB
Copy link
Collaborator

Simply merges codeql-cli/latest tag from upstream. No other changes.

tausbn and others added 30 commits January 30, 2026 12:50
Removes the dependence on the (global) `ModuleVariableNode.getARead()`,
by adding a local version (that doesn't include `import *` reads)
instead.
This may result in more nodes, but it should still be bounded by the
number of global variables in the source code.
With `ModuleVariableNode`s now appearing for _all_ global variables (not
just the ones that actually seem to be used), some of the tests changed
a bit. Mostly this was in the form of new flow (because of new nodes
that popped into existence). For some inline expectation tests, I opted
to instead exclude these results, as there was no suitable location to
annotate. For the normal tests, I just accepted the output (after having
vetted it carefully, of course).
Explicitly adds a bunch of nodes that were previously (using a global
analysis) identified as `ExtractedArgumentNode`s. These are then
subsequently filtered out in `argumentOf` (which is global) by putting
the call to `getCallArg` there instead of in the charpred.
Fixes the test failures that arose from making `ExtractedArgumentNode`
local.

For the consistency checks, we now explicitly exclude the
`ExtractedArgumentNode`s (now much more plentiful due to the
overapproximation) that don't have a corresponding `getCallArg` tuple.

For various queries/tests using `instanceof ArgumentNode`, we instead us
`isArgumentNode`, which explicitly filters out the ones for which
`isArgumentOf` doesn't hold (which, again, is the case for most of the
nodes in the overapproximation).
Uses the same trick as for `ExtractedArgumentNode`, wherein we postpone
the global restriction on the charpred to instead be in the `argumentOf`
predicate (which is global anyway).

In addition to this, we also converted `CapturedVariablesArgumentNode`
into a proper synthetic node, and added an explicit post-update node for
it. These nodes just act as wrappers for the function part of call
nodes. Thus, to make them work with the variable capture machinery, we
simply map them to the closure node for the corresponding control-flow
or post-update node.
As we now have many more capturing closure arguments, we must once again
exclude the ones that don't actually have `argumentOf` defined.
New nodes means new results. Luckily we rarely have a test that selects
_all_ dataflow nodes.
…rds-cpp

C++: Ensure that there are AST `GuardCondition`s for `||` and `&&`
…s-to-mad

Python: Allow models-as-data sanitizers
…eeds

C#: Make sure `allFeeds` contains at least `explicitFeeds`
Co-authored-by: Tom Hvitved <hvitved@github.com>
…ests

C#: Add more tests for `InsecureDirectObjectReference.ql`
Release preparation for version 2.24.1
…n-range-formatting

Fix formatting of Kotlin version ranges
Rust: Implement type inference for associated types for concrete types
owen-mc and others added 23 commits February 14, 2026 00:28
…t-of-line

Ruby: Add test cases for binary operator at start of line
Java: Add RegexMatch concept and recognise `@Pattern` annotation as sanitizer
…t-call-perf

Rust: Speedup type inference for `Trait::function()` calls
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ound-and-measure-enums

C++: Measure bounds for `Enum` constants and reduce `getBoundsLimit`
…-match

Java: Recognise `@Pattern` annotation as sanitizer for log injection
Release preparation for version 2.24.2
@ropwareJB ropwareJB enabled auto-merge February 23, 2026 18:59

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI 1 day ago

In general, the fix is to replace catch (Exception) with one or more catch clauses for specific, expected exception types that are safe to handle locally, and allow other exceptions to propagate.

For this snippet, the only code in the try block is:

return new FileInfo(config).Directory?.FullName;

The likely, non‑fatal exceptions from this are:

  • ArgumentException / ArgumentNullException / PathTooLongException — invalid path string.
  • NotSupportedException — invalid path format (e.g., URI).
  • SecurityException / UnauthorizedAccessException / IOException — problems accessing the file system.

Catching these and logging a warning preserves the intended behavior (skip problematic configs, log a warning, return null) while allowing more serious exceptions to bubble up.

The best minimal change is to replace the generic catch with a multi‑catch that targets these I/O and argument/path related exceptions. No additional methods or imports are required, since System and System.IO are already imported; the extra exception types (SecurityException, PathTooLongException) are also in System.

Concretely, in csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs, within the lambda passed to .Select(config => { ... }), change:

catch (Exception exc)
{
    logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}

to:

catch (IOException exc)
catch (UnauthorizedAccessException exc)
catch (ArgumentException exc)
catch (System.Security.SecurityException exc)
catch (PathTooLongException exc)
{
    logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}

(or equivalent grouping, depending on style), keeping the rest of the method intact.

Suggested changeset 1
csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs
--- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs
@@ -877,10 +877,26 @@
                         {
                             return new FileInfo(config).Directory?.FullName;
                         }
-                        catch (Exception exc)
+                        catch (IOException exc)
                         {
                             logger.LogWarning($"Failed to get directory of '{config}': {exc}");
                         }
+                        catch (UnauthorizedAccessException exc)
+                        {
+                            logger.LogWarning($"Failed to get directory of '{config}': {exc}");
+                        }
+                        catch (ArgumentException exc)
+                        {
+                            logger.LogWarning($"Failed to get directory of '{config}': {exc}");
+                        }
+                        catch (System.Security.SecurityException exc)
+                        {
+                            logger.LogWarning($"Failed to get directory of '{config}': {exc}");
+                        }
+                        catch (PathTooLongException exc)
+                        {
+                            logger.LogWarning($"Failed to get directory of '{config}': {exc}");
+                        }
                         return null;
                     })
                     .Where(folder => folder != null)
EOF
@@ -877,10 +877,26 @@
{
return new FileInfo(config).Directory?.FullName;
}
catch (Exception exc)
catch (IOException exc)
{
logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}
catch (UnauthorizedAccessException exc)
{
logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}
catch (ArgumentException exc)
{
logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}
catch (System.Security.SecurityException exc)
{
logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}
catch (PathTooLongException exc)
{
logger.LogWarning($"Failed to get directory of '{config}': {exc}");
}
return null;
})
.Where(folder => folder != null)
Copilot is powered by AI and may make mistakes. Always verify output.

Check notice

Code scanning / CodeQL

Call to 'System.IO.Path.Combine' may silently drop its earlier arguments Note

Call to 'System.IO.Path.Combine' may silently drop its earlier arguments.

Copilot Autofix

AI 1 day ago

To avoid Path.Combine silently dropping earlier arguments, we should ensure that later segments passed to it are not absolute paths. The general approaches are: (1) validate and reject absolute segments, (2) normalize absolute segments into relative ones, or (3) restructure combining logic so that only the base is absolute and subsequent segments are guaranteed relative. Using Path.Join alone does not solve the “absolute later argument overrides earlier ones” behavior; both Combine and Join behave similarly in this respect, so the fix must address the arguments themselves.

For this specific method, the best minimal fix is to sanitize subfolderName locally so that if it is an absolute path, we strip it down to its final directory/file name (using Path.GetFileName) before combining. FileUtils.ComputeHash(srcDir) is already a derived hash and not an absolute path, so it is safe. This change preserves existing behavior for all relative subfolderName values (the intended use), while ensuring that even if an absolute path somehow slips through, it will no longer cause the temp directory and hash to be ignored. Concretely, in ComputeTempDirectoryPath(string srcDir, string subfolderName) (around line 941 in csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs), introduce a local variable that normalizes subfolderName if Path.IsPathRooted(subfolderName) is true, and then use that variable in the Path.Combine call. No new imports or helper methods are required; everything is available from System.IO.

Suggested changeset 1
csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs
--- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs
@@ -938,7 +938,8 @@
         /// </summary>
         private static string ComputeTempDirectoryPath(string srcDir, string subfolderName)
         {
-            return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
+            var safeSubfolderName = Path.IsPathRooted(subfolderName) ? Path.GetFileName(subfolderName) : subfolderName;
+            return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), safeSubfolderName);
         }
     }
 }
EOF
@@ -938,7 +938,8 @@
/// </summary>
private static string ComputeTempDirectoryPath(string srcDir, string subfolderName)
{
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
var safeSubfolderName = Path.IsPathRooted(subfolderName) ? Path.GetFileName(subfolderName) : subfolderName;
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), safeSubfolderName);
}
}
}
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +707 to +711
catch
{
// If anything goes wrong, fall back to the unbound declaration.
return unboundDeclaration;
}

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI 1 day ago

In general, the fix is to replace the bare catch with one or more typed catch clauses that only handle the exceptions we actually expect from this sequence of operations, and optionally add a final catch that rethrows unexpected exceptions rather than silently swallowing them.

The best minimally invasive fix here is:

  • Catch specific, expected exceptions such as ArgumentException, InvalidOperationException, and NotSupportedException that can reasonably arise from:
    • SplitAt (index/argument errors),
    • Construct on INamedTypeSymbol,
    • LINQ First over the members.
  • Optionally add a second catch (Exception) that rethrows (or logs and rethrows) to avoid hiding truly unexpected failures. However, that would change behavior by no longer falling back for all exception types.
  • To avoid changing behavior, we should only handle the specific exceptions and allow everything else to propagate. This still changes behavior in edge cases (those previously swallowed), but in a safer direction and is aligned with the CodeQL recommendation while retaining the documented fallback for anticipated failures.

No new imports are needed; the exception types are in System, which is already imported at the top of the file. The only change is to the catch clause around lines 693–697 in csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs.

Suggested changeset 1
csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
--- a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
@@ -690,11 +690,21 @@
                             ? extensionDeclaration.Construct(extensionMethodArguments.ToArray())
                             : extensionDeclaration;
                     }
-                    catch
+                    catch (ArgumentException)
                     {
                         // If anything goes wrong, fall back to the unbound declaration.
                         return unboundDeclaration;
                     }
+                    catch (InvalidOperationException)
+                    {
+                        // If anything goes wrong, fall back to the unbound declaration.
+                        return unboundDeclaration;
+                    }
+                    catch (NotSupportedException)
+                    {
+                        // If anything goes wrong, fall back to the unbound declaration.
+                        return unboundDeclaration;
+                    }
                 }
                 else
                 {
EOF
@@ -690,11 +690,21 @@
? extensionDeclaration.Construct(extensionMethodArguments.ToArray())
: extensionDeclaration;
}
catch
catch (ArgumentException)
{
// If anything goes wrong, fall back to the unbound declaration.
return unboundDeclaration;
}
catch (InvalidOperationException)
{
// If anything goes wrong, fall back to the unbound declaration.
return unboundDeclaration;
}
catch (NotSupportedException)
{
// If anything goes wrong, fall back to the unbound declaration.
return unboundDeclaration;
}
}
else
{
Copilot is powered by AI and may make mistakes. Always verify output.

Check notice

Code scanning / CodeQL

Nested 'if' statements can be combined Note

These 'if' statements can be combined.

Copilot Autofix

AI 1 day ago

In general, to fix this kind of issue you replace nested if statements that lack else branches with a single if statement whose condition is the logical && of the original conditions. You must ensure there is no intervening code whose execution would be altered and that operator precedence is clear (using parentheses where necessary).

For this specific case in csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs, inside GetParameterKind(this IParameterSymbol parameter), we should combine:

if (parameter.Ordinal == 0)
{
    if (parameter.ContainingSymbol is IMethodSymbol method && method.IsExtensionMethod)
    {
        return Parameter.Kind.This;
    }
}

into a single if:

if (parameter.Ordinal == 0 &&
    parameter.ContainingSymbol is IMethodSymbol method &&
    method.IsExtensionMethod)
{
    return Parameter.Kind.This;
}

This keeps existing functionality intact: Parameter.Kind.This is returned only when the parameter is the first parameter (Ordinal == 0) and belongs to an extension method. No imports, new methods, or additional definitions are required; we only refactor the condition and block structure within the shown method.

Suggested changeset 1
csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
--- a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
@@ -837,12 +837,11 @@
                     if (parameter.IsParams)
                         return Parameter.Kind.Params;
 
-                    if (parameter.Ordinal == 0)
+                    if (parameter.Ordinal == 0 &&
+                        parameter.ContainingSymbol is IMethodSymbol method &&
+                        method.IsExtensionMethod)
                     {
-                        if (parameter.ContainingSymbol is IMethodSymbol method && method.IsExtensionMethod)
-                        {
-                            return Parameter.Kind.This;
-                        }
+                        return Parameter.Kind.This;
                     }
                     return Parameter.Kind.None;
             }
EOF
@@ -837,12 +837,11 @@
if (parameter.IsParams)
return Parameter.Kind.Params;

if (parameter.Ordinal == 0)
if (parameter.Ordinal == 0 &&
parameter.ContainingSymbol is IMethodSymbol method &&
method.IsExtensionMethod)
{
if (parameter.ContainingSymbol is IMethodSymbol method && method.IsExtensionMethod)
{
return Parameter.Kind.This;
}
return Parameter.Kind.This;
}
return Parameter.Kind.None;
}
Copilot is powered by AI and may make mistakes. Always verify output.
@dilanbhalla dilanbhalla disabled auto-merge February 23, 2026 21:56
@dilanbhalla dilanbhalla merged commit 9cf0c79 into main Feb 23, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.