Skip to content

Warn and block outdated Dolphin launches - #314

Open
patchzyy wants to merge 1 commit into
devfrom
DolphinWarning
Open

Warn and block outdated Dolphin launches#314
patchzyy wants to merge 1 commit into
devfrom
DolphinWarning

Conversation

@patchzyy

@patchzyy patchzyy commented Aug 11, 2026

Copy link
Copy Markdown
Member

Purpose of this PR:

Force users to use newest dolphin version to avoid the Dolphin DSP-HLE Guest-to-Host RCE

How to Test:

Dolphin dolphin version 2606, link it to wheelwizard and try to launch your game, you should get a popup warning that this version is vulnerable, updating to 2606a should not give this popup

What Has Been Changed:

A new DolphinVersionService has been created

Related Issue Link:

none

Checklist before merging

  • You have created relevant tests

Summary by CodeRabbit

  • New Features
    • Added Dolphin version detection, identifying supported, outdated, and unrecognized installations.
    • Outdated Dolphin versions now prompt users to update or continue at their own risk.
    • Linux Flatpak installations can be updated in place with progress reporting.
    • Other installations provide a link to download the latest Dolphin version.
    • Added clearer update, warning, success, and “play anyway” messages.
  • Bug Fixes
    • Dolphin launch actions now wait for update checks and launch completion before proceeding.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Dolphin version and launch update

Layer / File(s) Summary
Version parsing and detection
WheelWizard/Features/DolphinInstaller/DolphinVersion.cs, WheelWizard/Features/DolphinInstaller/DolphinVersionService.cs, WheelWizard/Features/DolphinInstaller/DolphinInstallerExtensions.cs, WheelWizard.Test/Features/DolphinVersionTests.cs
Adds Dolphin version parsing, status classification, platform-specific probing, fallback detection, dependency registration, and coverage for supported, outdated, and unknown inputs.
Flatpak update and app-ID handling
WheelWizard/Features/DolphinInstaller/LinuxDolphinInstaller.cs, WheelWizard/Services/PathManager.cs, WheelWizard.Test/Features/LinuxDolphinInstallerTests.cs
Adds Flatpak app-ID extraction and Flatpak update execution with progress reporting and explicit failure results.
Version-gated Dolphin launch
WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs, WheelWizard/Views/Popups/Generic/YesNoWindow.axaml.cs, WheelWizard/Resources/Languages/en.yml
Makes Dolphin launch asynchronous, checks configured versions, prompts for outdated versions, runs or redirects updates, and supports explicit play-anyway handling.
Asynchronous launch callers
WheelWizard/Services/Launcher/MiiChannelLaunchHelper.cs, WheelWizard/Services/Launcher/RrLauncher.cs, WheelWizard/Services/Launcher/RrBetaLauncher.cs, WheelWizard/Views/Pages/HomePage.axaml.cs, WheelWizard/Views/Popups/DevToolWindow.axaml.cs
Awaits Dolphin launch operations from launcher services and UI event handlers.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LaunchDolphin
  participant DolphinVersionService
  participant YesNoWindow
  participant ILinuxDolphinInstaller
  LaunchDolphin->>DolphinVersionService: CheckConfiguredDolphin()
  DolphinVersionService-->>LaunchDolphin: return status and version
  LaunchDolphin->>YesNoWindow: prompt for outdated version
  YesNoWindow-->>LaunchDolphin: return update or play-anyway choice
  LaunchDolphin->>ILinuxDolphinInstaller: UpdateFlatpakDolphin(appId, progress)
  ILinuxDolphinInstaller-->>LaunchDolphin: return update result
Loading

Possibly related PRs

Suggested reviewers: dirkdoes

Poem

I checked each Dolphin by moonlight bright,
Found old builds hiding out of sight.
Update the Flatpak, or choose to play,
Then launch the game the proper way.
The rabbit hops through tests with cheer.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: warning users and blocking launches for outdated Dolphin versions.
Description check ✅ Passed The description covers the purpose, test steps, changed component, issue status, and relevant tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DolphinWarning

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@WheelWizard/Features/DolphinInstaller/DolphinVersion.cs`:
- Around line 89-90: Update the development-build handling in GetStatus to use
int.TryParse instead of int.Parse; return DolphinVersionStatus.Unknown when
parsing fails, while preserving the minimum-build comparison for valid values.
Add a DolphinVersionTests case covering an oversized development build number
and the expected Unknown status.

In `@WheelWizard/Features/DolphinInstaller/LinuxDolphinInstaller.cs`:
- Around line 108-123: Add direct tests for
LinuxDolphinInstaller.UpdateFlatpakDolphin covering unavailable Flatpak, process
failure, nonzero exit code, and successful execution. Verify the process service
receives “flatpak” with “update -y <appId>” and the same progress instance,
while asserting each expected OperationResult outcome.

In `@WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs`:
- Around line 198-203: Expose an explicit outcome from
DolphinLaunchHelper.LaunchDolphin and add a reusable version preflight that
callers can run before destructive preparation; return a non-success outcome
when ConfirmDolphinVersionAsync blocks launch. In
WheelWizard/Services/Launcher/Helpers/MiiChannelLaunchHelper.cs:38, run the
preflight before enabling the virtual Wii Remote and avoid retaining Mii Channel
launch state when blocked. In
WheelWizard/Services/Launcher/RrBetaLauncher.cs:58-60 and
WheelWizard/Services/Launcher/RrLauncher.cs:59-61, run the preflight before
killing Dolphin or preparing mods/patches, and return a non-success result when
launch does not proceed.

In `@WheelWizard/Services/PathManager.cs`:
- Around line 690-696: Update ExtractDolphinFlatpakAppId to parse the flatpak
run arguments and return the application-ID operand immediately following run,
rather than selecting the last app-ID-shaped match. Ignore app-ID-shaped values
belonging to options such as --command, preserve the default fallback for
missing or invalid input, and add coverage for commands containing app-ID-shaped
option values.

In `@WheelWizard/Views/Pages/HomePage.axaml.cs`:
- Around line 102-105: Update DolphinButton_OnClick to disable CompleteGrid
before awaiting DolphinLaunchHelper.LaunchDolphin, preventing concurrent launch
flows during prompts or updates. Keep the existing DisableAllButtonsTemporarily
cooldown, and re-enable CompleteGrid in a finally block after that cooldown
completes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ed8310fa-d91b-4995-84ed-10ad47c58053

📥 Commits

Reviewing files that changed from the base of the PR and between b56b11e and da938c8.

📒 Files selected for processing (16)
  • WheelWizard.Test/Features/DolphinVersionTests.cs
  • WheelWizard.Test/Features/LinuxDolphinInstallerTests.cs
  • WheelWizard/Features/DolphinInstaller/DolphinInstallerExtensions.cs
  • WheelWizard/Features/DolphinInstaller/DolphinVersion.cs
  • WheelWizard/Features/DolphinInstaller/DolphinVersionService.cs
  • WheelWizard/Features/DolphinInstaller/LinuxDolphinInstaller.cs
  • WheelWizard/Features/Settings/SettingsManager.cs
  • WheelWizard/Resources/Languages/en.yml
  • WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs
  • WheelWizard/Services/Launcher/Helpers/MiiChannelLaunchHelper.cs
  • WheelWizard/Services/Launcher/RrBetaLauncher.cs
  • WheelWizard/Services/Launcher/RrLauncher.cs
  • WheelWizard/Services/PathManager.cs
  • WheelWizard/Views/Pages/HomePage.axaml.cs
  • WheelWizard/Views/Popups/DevToolWindow.axaml.cs
  • WheelWizard/Views/Popups/Generic/YesNoWindow.axaml.cs

Comment on lines +89 to +90
if (devBuildGroup.Success)
return int.Parse(devBuildGroup.Value) >= MinimumDevBuild;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e

printf '%s\n' '--- target file outline ---'
ast-grep outline WheelWizard/Features/DolphinInstaller/DolphinVersion.cs 2>/dev/null || true

printf '%s\n' '--- target implementation ---'
sed -n '1,180p' WheelWizard/Features/DolphinInstaller/DolphinVersion.cs

printf '%s\n' '--- related call sites and tests ---'
rg -n -C 5 'GetStatus|CheckConfiguredDolphin|DolphinVersionTests|MinimumDevBuild|devBuildGroup' . \
  -g '*.cs' -g '*.csproj' -g '*.sln' || true

Repository: TeamWheelWizard/WheelWizard

Length of output: 27609


🏁 Script executed:

#!/bin/bash
set -e

python3 - <<'PY'
import re

pattern = re.compile(r'(?<![\w.])(?P<yearMonth>\d{4})(?P<revision>[a-z]?)(?:-(?P<devBuild>\d+))?(?![\w.])')
text = '2606-999999999999999999999'
match = pattern.search(text)
value = match.group('devBuild') if match else None
print(f'input={text!r}')
print(f'match={match.group(0)!r}')
print(f'devBuild={value!r}')
print(f'digits={len(value)}')
print(f'Int32.MaxValue={2**31 - 1}')
print(f'fits_Int32={value is not None and int(value) <= 2**31 - 1}')
PY

printf '%s\n' '--- service contract and call path ---'
cat -n WheelWizard/Features/DolphinInstaller/DolphinVersionService.cs | sed -n '1,52p'
cat -n WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs | sed -n '125,145p'

printf '%s\n' '--- relevant test file ---'
cat -n WheelWizard.Test/Features/DolphinVersionTests.cs | sed -n '1,90p'

Repository: TeamWheelWizard/WheelWizard

Length of output: 6970


Handle oversized development build numbers without throwing.

VersionPattern accepts unbounded digits, but int.Parse throws OverflowException for values such as 2606-999999999999999999999. CheckConfiguredDolphin does not catch exceptions from GetStatus, despite its never-throws contract. Use int.TryParse and return DolphinVersionStatus.Unknown when parsing fails. Add this case to DolphinVersionTests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WheelWizard/Features/DolphinInstaller/DolphinVersion.cs` around lines 89 -
90, Update the development-build handling in GetStatus to use int.TryParse
instead of int.Parse; return DolphinVersionStatus.Unknown when parsing fails,
while preserving the minimum-build comparison for valid values. Add a
DolphinVersionTests case covering an oversized development build number and the
expected Unknown status.

Comment on lines +108 to +123
public async Task<OperationResult> UpdateFlatpakDolphin(string appId, IProgress<int>? progress = null)
{
if (!IsFlatpakInstalled())
return Fail("Flatpak is not available, so Dolphin cannot be updated automatically.");

// No installation scope flag on purpose: Flatpak resolves whichever installation actually
// holds the app. A system-wide install may still refuse without elevation, which surfaces
// as a non-zero exit code and lets the caller fall back to the download page.
var updateResult = await processService.RunWithProgressAsync("flatpak", $"update -y {appId}", progress);
if (updateResult.IsFailure)
return updateResult.Error;

if (updateResult.Value != 0)
return Fail($"Dolphin update failed with exit code {updateResult.Value}.");

return Ok();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add direct tests for UpdateFlatpakDolphin.

The supplied LinuxDolphinInstallerTests class has no coverage for this new operation. Add tests for unavailable Flatpak, process failure, nonzero exit code, and successful execution. Assert that the command is flatpak update -y <appId> and that the progress instance is forwarded.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WheelWizard/Features/DolphinInstaller/LinuxDolphinInstaller.cs` around lines
108 - 123, Add direct tests for LinuxDolphinInstaller.UpdateFlatpakDolphin
covering unavailable Flatpak, process failure, nonzero exit code, and successful
execution. Verify the process service receives “flatpak” with “update -y
<appId>” and the same progress instance, while asserting each expected
OperationResult outcome.

Comment on lines 198 to +203
// Make sure all file arguments are absolute paths
public static void LaunchDolphin(string arguments = "", bool shellExecute = false)
public static async Task LaunchDolphin(string arguments = "", bool shellExecute = false)
{
if (!await ConfirmDolphinVersionAsync())
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Expose the version-gate outcome before launcher preparation.

LaunchDolphin can return without starting Dolphin when the user dismisses the outdated-version prompt or starts an update. It returns Task, so callers cannot distinguish that case from a successful launch. The Retro Rewind launchers then return Ok() after they already killed Dolphin and modified launch state.

  • WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs#L198-L203: return an explicit launch outcome and provide a version preflight that callers can run before destructive preparation.
  • WheelWizard/Services/Launcher/Helpers/MiiChannelLaunchHelper.cs#L38-L38: run the preflight before enabling the virtual Wii Remote. Do not retain Mii Channel launch state when the launch is blocked.
  • WheelWizard/Services/Launcher/RrBetaLauncher.cs#L58-L60: run the preflight before killing Dolphin or preparing mods. Return a non-success result when launch does not proceed.
  • WheelWizard/Services/Launcher/RrLauncher.cs#L59-L61: run the preflight before killing Dolphin or preparing patches. Return a non-success result when launch does not proceed.
📍 Affects 4 files
  • WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs#L198-L203 (this comment)
  • WheelWizard/Services/Launcher/Helpers/MiiChannelLaunchHelper.cs#L38-L38
  • WheelWizard/Services/Launcher/RrBetaLauncher.cs#L58-L60
  • WheelWizard/Services/Launcher/RrLauncher.cs#L59-L61
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WheelWizard/Services/Launcher/Helpers/DolphinLaunchHelper.cs` around lines
198 - 203, Expose an explicit outcome from DolphinLaunchHelper.LaunchDolphin and
add a reusable version preflight that callers can run before destructive
preparation; return a non-success outcome when ConfirmDolphinVersionAsync blocks
launch. In WheelWizard/Services/Launcher/Helpers/MiiChannelLaunchHelper.cs:38,
run the preflight before enabling the virtual Wii Remote and avoid retaining Mii
Channel launch state when blocked. In
WheelWizard/Services/Launcher/RrBetaLauncher.cs:58-60 and
WheelWizard/Services/Launcher/RrLauncher.cs:59-61, run the preflight before
killing Dolphin or preparing mods/patches, and return a non-success result when
launch does not proceed.

Comment on lines +690 to +696
public static string ExtractDolphinFlatpakAppId(string flatpakDolphinLocation)
{
if (string.IsNullOrWhiteSpace(flatpakDolphinLocation))
return DefaultDolphinFlatpakAppId;

var matches = Regex.Matches(flatpakDolphinLocation, @"(?i)\b[a-z][a-z0-9]*(?:\.[a-z_][a-z0-9_]*){1,}\.[a-z_][a-z0-9_-]*\b");
return matches.Count == 0 ? DefaultDolphinFlatpakAppId : matches[^1].Value;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Extract the application ID from the flatpak run argument position.

Line 696 selects the last app-ID-shaped value in the complete command. For example, flatpak run org.DolphinEmu.dolphin-emu --command=org.example.Tool returns org.example.Tool, not the Dolphin application ID.

This causes flatpak info and flatpak update to target the wrong application. Version detection then returns Unknown and allows a vulnerable Dolphin launch. Parse the flatpak run arguments and select its application-ID operand. Add cases with app-ID-shaped option values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WheelWizard/Services/PathManager.cs` around lines 690 - 696, Update
ExtractDolphinFlatpakAppId to parse the flatpak run arguments and return the
application-ID operand immediately following run, rather than selecting the last
app-ID-shaped match. Ignore app-ID-shaped values belonging to options such as
--command, preserve the default fallback for missing or invalid input, and add
coverage for commands containing app-ID-shaped option values.

Comment on lines +102 to 105
private async void DolphinButton_OnClick(object? sender, RoutedEventArgs e)
{
DolphinLaunchHelper.LaunchDolphin();
await DolphinLaunchHelper.LaunchDolphin();
DisableAllButtonsTemporarily();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Disable launch controls before awaiting the launch flow.

The button remains enabled during the version prompt and Flatpak update. Multiple clicks can start duplicate launch flows.

Disable CompleteGrid before await DolphinLaunchHelper.LaunchDolphin(). Re-enable it in finally after the existing cooldown.

Proposed fix
 private async void DolphinButton_OnClick(object? sender, RoutedEventArgs e)
 {
-    await DolphinLaunchHelper.LaunchDolphin();
-    DisableAllButtonsTemporarily();
+    CompleteGrid.IsEnabled = false;
+    try
+    {
+        await DolphinLaunchHelper.LaunchDolphin();
+    }
+    finally
+    {
+        DisableAllButtonsTemporarily();
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private async void DolphinButton_OnClick(object? sender, RoutedEventArgs e)
{
DolphinLaunchHelper.LaunchDolphin();
await DolphinLaunchHelper.LaunchDolphin();
DisableAllButtonsTemporarily();
private async void DolphinButton_OnClick(object? sender, RoutedEventArgs e)
{
CompleteGrid.IsEnabled = false;
try
{
await DolphinLaunchHelper.LaunchDolphin();
}
finally
{
DisableAllButtonsTemporarily();
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WheelWizard/Views/Pages/HomePage.axaml.cs` around lines 102 - 105, Update
DolphinButton_OnClick to disable CompleteGrid before awaiting
DolphinLaunchHelper.LaunchDolphin, preventing concurrent launch flows during
prompts or updates. Keep the existing DisableAllButtonsTemporarily cooldown, and
re-enable CompleteGrid in a finally block after that cooldown completes.

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.

1 participant