Skip to content

Share: Handle exhaustive switches in the shared CFG library - #23026

Open
paldepind wants to merge 6 commits into
mainfrom
unified/match-all
Open

paldepind wants to merge 6 commits into
mainfrom
unified/match-all

Conversation

@paldepind

@paldepind paldepind commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

This PR:

  • In the shared library:
    • Adds support for exhaustive switch statements/expressions.
    • Removes DefaultCase case handling from the default matchAll implementation. This makes it possible to customize matchAll without having to re-implement DefaultCase handling.
  • Unified+Swift
    • Makes use of the new exhaustive switch handling. This improves the CFG for Swift.
  • In Java and C#
    • Adapt to the changes in the shared library. This reduces code while preserving behavior.

@paldepind paldepind changed the title Share exhaustive-switch handling across Unified and Java CFGs Shared: Handle exhaustive switches in the shared CFG library Nov 5, 2026
@paldepind paldepind changed the title Shared: Handle exhaustive switches in the shared CFG library Share exhaustive-switch and default-case handling across CFGs Nov 5, 2026
@paldepind paldepind changed the title Share exhaustive-switch and default-case handling across CFGs Share: Handle exhaustive switches in the shared CFG library Nov 5, 2026
paldepind and others added 5 commits November 5, 2026 12:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a9b52f8-d07b-4692-8fb9-409f0efd64f2
Add an `isExhaustive` input hook and treat the final case of an
exhaustive switch as match-all. Default to non-exhaustive to preserve
existing behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a9b52f8-d07b-4692-8fb9-409f0efd64f2
Use the shared exhaustive-switch handling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a9b52f8-d07b-4692-8fb9-409f0efd64f2
Declare exhaustive Java switch constructs through `isExhaustive`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a9b52f8-d07b-4692-8fb9-409f0efd64f2
Keep only language-specific switch-arm match-all logic, since the shared
control-flow graph now handles default cases directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a9b52f8-d07b-4692-8fb9-409f0efd64f2
@paldepind
paldepind marked this pull request as ready for review November 5, 2026 11:56
@paldepind
paldepind requested review from a team as code owners November 5, 2026 11:56
Copilot AI auto review requested due to automatic review settings November 5, 2026 11:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical exhaustiveness inference errors can make default arms unreachable and remove valid Swift switch continuations, potentially hiding downstream taint flows.

2 open issues
What changed in this PR

Adds exhaustive-switch support to the shared control-flow graph library, allowing Unified’s Swift analysis to remove impossible fall-through paths while adapting the Java and C# integrations.

Changes:

  • Introduce isExhaustive and centralize default-case handling in the shared CFG.
  • Enable exhaustive Swift switches and update Java and C# matching hooks.
  • Add Swift Boolean and enum switch tests and refresh expected CFG results.
File Description
unified/​ql/​test/​library-tests/​controlflow/​cfg.swift Add exhaustive Boolean and enum switch tests, including a guarded case.
unified/​ql/​test/​library-tests/​controlflow/​cfg.expected Record case edges and unreachable post-switch returns.
unified/​ql/​test/​library-tests/​controlflow/​basicblock-slices.expected Update basic-block expectations for the new tests.
unified/​ql/​lib/​codeql/​unified/​internal/​ControlFlowGraph.qll Mark Swift switches as exhaustive.
shared/​controlflow/​codeql/​controlflow/​ControlFlowGraph.qll Add the exhaustiveness hook and shared match-all handling.
java/​ql/​lib/​semmle/​code/​java/​ControlFlowGraph.qll Separate switch exhaustiveness from match-all patterns.
csharp/​ql/​lib/​semmle/​code/​csharp/​controlflow/​ControlFlowGraph.qll Delegate default-case handling to the shared library.

Review effort: Max (auto)

Input1::matchAll(c)
or
exists(Switch switch, int last |
Input1::isExhaustive(switch) and

@paldepind paldepind Nov 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this problem existed before this PR as well. But it's valid and I've applied the suggestion.

@paldepind
paldepind requested an auto review from Copilot November 5, 2026 12:22
@paldepind paldepind added the no-change-note-required This PR does not need a change note label Nov 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The switch-exhaustiveness guard misses default cases outside the AST-last position, incorrectly treating a later case as match-all and making the default arm unreachable in the CFG.

2 open issues
1 resolved since last review

Review effort: Max (auto)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C# Java no-change-note-required This PR does not need a change note Unified

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants