Skip to content

[Windows] Fix password Entry crash when setting text on empty field#33891

Merged
kubaflo merged 4 commits intodotnet:inflight/currentfrom
praveenkumarkarunanithi:fix-33334
Apr 12, 2026
Merged

[Windows] Fix password Entry crash when setting text on empty field#33891
kubaflo merged 4 commits intodotnet:inflight/currentfrom
praveenkumarkarunanithi:fix-33334

Conversation

@praveenkumarkarunanithi
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Root Cause

When a password Entry field is empty and text is programmatically set, the obfuscation logic calculates a negative insert position (0 - 4 = -4). String. Insert() doesn't accept negative indices, causing an ArgumentOutOfRangeException crash in windows.

Description of Change

Added Math.Max(0, ...) to clamp the insert position to a minimum of 0, preventing negative values.

Issues Fixed

Fixes #33334

Platforms Tested

  • iOS
  • Android
  • Windows
  • Mac

Screenshots

Before Fix After Fix
withoutfix withfix

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Feb 4, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review February 4, 2026 14:20
Copilot AI review requested due to automatic review settings February 4, 2026 14:20
@sheiksyedm sheiksyedm added the community ✨ Community Contribution label Feb 4, 2026
@sheiksyedm sheiksyedm added this to the .NET 10 Servicing milestone Feb 4, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a Windows-specific crash in password Entry fields when text is programmatically set on an empty field. The crash occurred because the obfuscation logic calculated a negative insert position when the field was empty, causing ArgumentOutOfRangeException in the String.Insert() method.

Changes:

  • Added Math.Max(0, ...) to clamp the insert position to prevent negative values in the password obfuscation logic
  • Added a device test to verify that setting text on an empty password Entry does not crash

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Core/src/Platform/Windows/MauiPasswordTextBox.cs Fixed the insert position calculation to prevent negative indices by using Math.Max(0, ...)
src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.Windows.cs Added test to verify password Entry doesn't crash when text is set on empty field

Comment on lines +135 to +136

// Setting Text on an empty password entry triggers TextChanging event which previously threw ArgumentOutOfRangeException
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The comment is not properly indented. It should be indented with two tabs to align with the code below it.

Suggested change
// Setting Text on an empty password entry triggers TextChanging event which previously threw ArgumentOutOfRangeException
// Setting Text on an empty password entry triggers TextChanging event which previously threw ArgumentOutOfRangeException

Copilot uses AI. Check for mistakes.
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Feb 4, 2026

📋 PR Finalization Review

Title: ✅ Good

Current: [Windows] Fix password Entry crash when setting text on empty field

Description: ✅ Good

Excellent description:

  • Clear Root Cause explaining the specific calculation issue (0 - 4 = -4)
  • Accurate Description of Change matching the implementation (Math.Max(0, ...))
  • Issues Fixed section with linked issue
  • Platforms Tested checklist
  • Before/After screenshots included
  • NOTE block present at top
Code Review: ✅ Passed

✅ Looks Good

1. Simple, surgical fix

  • The one-line change Math.Max(0, start - lengthDifference) directly addresses the root cause
  • No over-engineering - just defensive programming to prevent negative index

2. Proper test coverage

  • Added Windows-specific device test PasswordEntryPlatformSetDoesNotCrash
  • Test creates empty password Entry, sets text programmatically, verifies no crash
  • Test comment explains the scenario that previously threw ArgumentOutOfRangeException

3. Defensive programming approach

  • Using Math.Max(0, ...) ensures insert position can never be negative regardless of edge cases

🟡 Minor Suggestions (Optional)

1. Test comment indentation (line 128)

  • The comment // Setting Text on an empty password entry... has inconsistent indentation
  • Minor cosmetic issue only

2. Test assertion could be stronger

  • Current: Assert.NotNull(passwordTextBox.Text)
  • Could also add: Assert.Equal("test", passwordTextBox.Text) to confirm text was set correctly

Verdict: ✅ This PR is ready for merge. The fix is minimal, correct, well-documented, and properly tested.

@PureWeen PureWeen modified the milestones: .NET 10 Servicing, Backlog Mar 3, 2026
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels Mar 20, 2026
@MauiBot MauiBot removed the s/agent-changes-requested AI agent recommends changes - found a better alternative or issues label Mar 28, 2026
@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels Mar 28, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 5, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please implement the ai's suggestions?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 8, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 33891

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 33891"

@praveenkumarkarunanithi
Copy link
Copy Markdown
Contributor Author

🤖 AI Summary

📊 Expand Full Review048e4ac · update tests
🔍 Pre-Flight — Context & Validation
Issue: #33334 - [WinUI] Password Obfuscation causes unhandled crash PR: #33891 - [Windows] Fix password Entry crash when setting text on empty field Platforms Affected: Windows only Files Changed: 1 implementation, 1 test

Key Findings

  • Crash occurs in MauiPasswordTextBox.DetermineTextFromPassword when realText is empty ("") and passwordText is non-empty. lengthDifference > 0, so start - lengthDifference = 0 - 4 = -4 is passed to String.Insert(). In unchecked context, -1 wraps to UInt32.MaxValue (4294967295), causing ArgumentOutOfRangeException.
  • Issue verified by Syncfusion contributor (label s/verified). Production crash trace shows startIndex ('4294967295') must be less than or equal to '0'.
  • PR fix: Math.Max(0, start - lengthDifference) in the Insert branch of DetermineTextFromPassword. Minimal one-line change.
  • Gate FAILED — both "without fix" and "with fix" builds failed with WindowsAppSDKSelfContained requires a supported Windows architecture in Graphics.csproj. This is an environment/CI architecture issue unrelated to the PR changes.
  • Unresolved inline review comment (from copilot-pull-request-reviewer): line 136 in EntryTests.Windows.cs has incorrect indentation on the comment (1 tab instead of 2 tabs).
  • Remove branch not guarded: The else if (lengthDifference < 0) branch calls realText.Remove(start, -lengthDifference) without bounds checks — could throw ArgumentOutOfRangeException if start > realText.Length or start + (-lengthDifference) > realText.Length.
  • Prior pr-finalize review by kubaflo (MEMBER): ✅ with only minor optional suggestions.
  • Prior agent review (MauiBot, 2026-04-05): Recommended REQUEST CHANGES citing Remove branch and indentation.
  • Test assertion Assert.NotNull(passwordTextBox.Text) only verifies non-null, not actual text value.

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #33891 Math.Max(0, start - lengthDifference) to clamp Insert index ❌ Gate FAILED (env build error) MauiPasswordTextBox.cs Logically correct; build env blocked validation
🔧 Fix — Analysis & Comparison

Fix Candidates

Source Approach Test Result Files Changed Notes

1 try-fix (claude-opus-4.6) Early-return guard when realText empty + Math.Clamp on both Insert and Remove branches ⚠️ BLOCKED MauiPasswordTextBox.cs Build env: WindowsAppSDKSelfContained arch error
2 try-fix (claude-sonnet-4.6) Long arithmetic (cast to long) + Math.Clamp on both branches ⚠️ BLOCKED MauiPasswordTextBox.cs Build env: same error
3 try-fix (gpt-5.3-codex) Caller-level bypass — skip DetermineTextFromPassword when Password is empty ⚠️ BLOCKED MauiPasswordTextBox.cs Build env: same error
4 try-fix (gpt-5.4) Pure character-level merge loop rewrite of DetermineTextFromPassword — no Insert/Remove ⚠️ BLOCKED MauiPasswordTextBox.cs Build env: same error
PR PR #33891 Math.Max(0, start - lengthDifference) to clamp Insert index ❌ Gate FAILED (env build error) MauiPasswordTextBox.cs Logically correct; same env blocks validation

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No NO NEW IDEAS — solution space exhausted across 5 approaches
Exhausted: Yes Selected Fix: PR's fix (Math.Max(0, start - lengthDifference)) — All 4 try-fix alternatives were BLOCKED by the same build environment limitation (WindowsAppSDKSelfContained requires a supported Windows architecture). No empirical comparison was possible. The PR's fix is the simplest and most surgical. Attempt 1 provides a more comprehensive variant (both branches guarded), but cannot be validated in this environment.

📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #33334 confirmed, Windows-only crash in DetermineTextFromPassword
Gate ❌ FAILED Windows — build env error (not code): WindowsAppSDKSelfContained requires a supported Windows architecture
Try-Fix ✅ COMPLETE 4 attempts, 0 passing (all ⚠️ BLOCKED — same build env limitation)
Report ✅ COMPLETE

Summary

PR #33891 fixes a Windows-only ArgumentOutOfRangeException crash in MauiPasswordTextBox.DetermineTextFromPassword with a minimal one-line change. The fix is logically correct. The Gate failed due to a build environment limitation unrelated to the PR code. All 4 try-fix attempts were blocked by the same environment issue. There are actionable code issues that should be addressed before merging.

Root Cause

When a password Entry is empty (realText = "") and text is programmatically set, TextChanging fires with SelectionStart = 0. DetermineTextFromPassword("", 0, "test") computes lengthDifference = 4 and calls "".Insert(0 - 4, "●●●●")Insert(-4, ...). In unchecked arithmetic, -4 wraps to a large uint value (4294967295), causing ArgumentOutOfRangeException.

Fix Quality

The Insert branch fix is correct and minimal. Math.Max(0, start - lengthDifference) prevents the negative index for the reported crash scenario.

Issues requiring changes:

  1. ⚠️ Remove branch not guarded (potential crash): The else if (lengthDifference < 0) branch calls realText.Remove(start, -lengthDifference) without bounds validation. If start > realText.Length or start + (-lengthDifference) > realText.Length, this will also throw ArgumentOutOfRangeException. The same defensive programming should apply:
    else if (lengthDifference < 0)
    {
        var removeCount = Math.Min(-lengthDifference, realText.Length - Math.Min(start, realText.Length));
        if (start < realText.Length && removeCount > 0)
            realText = realText.Remove(start, removeCount);
    }
  2. ⚠️ Unresolved inline review comment (indentation): Line 136 in EntryTests.Windows.cs has a comment with incorrect indentation (1 tab instead of 2 tabs). The inline suggestion from copilot-pull-request-reviewer has not been applied.
  3. 💡 Weak test assertion: Assert.NotNull(passwordTextBox.Text) only verifies non-null. Assert.Equal("test", passwordTextBox.Text) would confirm the text was actually set correctly, making the test more meaningful.
  4. ℹ️ Gate failure is environmental (not blocking): The build error occurs in Graphics.csproj transitive dependency and is unrelated to the PR's code changes.

Selected Fix

PR's fix — it is logically sound for the reported scenario. No try-fix candidate empirically outperformed it (all blocked). Before merging, the Remove branch should also be guarded and the indentation issue resolved.

The “Remove branch not guarded” concern was reviewed and validated. The delete path is only triggered through user-driven input where indices remain within valid bounds, and no crash was reproducible during testing. Unlike the insert scenario, it is not affected by programmatic edge cases, so no change is required.

@praveenkumarkarunanithi
Copy link
Copy Markdown
Contributor Author

Could you please implement the ai's suggestions?

Checked the AI suggestions and addressed the applicable ones.

@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

kubaflo
kubaflo previously approved these changes Apr 10, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current April 10, 2026 09:00
@kubaflo kubaflo changed the base branch from inflight/current to main April 10, 2026 09:01
@kubaflo kubaflo dismissed their stale review April 10, 2026 09:01

The base branch was changed.

@dotnet dotnet deleted a comment from MauiBot Apr 10, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 10, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 10, 2026

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate3e97d6b · fixed test condition as per AI concerns.

Gate Result: ❌ FAILED

Platform: WINDOWS · Base: main · Merge base: b43bdad1

Test Without Fix (expect FAIL) With Fix (expect PASS)
📱 EntryTests (PasswordEntryPlatformSetDoesNotCrash) Category=Entry ✅ FAIL — 104s ❌ FAIL — 18s
🔴 Without fix — 📱 EntryTests (PasswordEntryPlatformSetDoesNotCrash): FAIL ✅ · 104s
  Determining projects to restore...
  Restored D:\a\1\s\src\Controls\src\Xaml\Controls.Xaml.csproj (in 1.29 min).
  Restored D:\a\1\s\src\Controls\src\Xaml.Design\Controls.Xaml.Design.csproj (in 22 ms).
  Restored D:\a\1\s\src\Controls\tests\DeviceTests\Controls.DeviceTests.csproj (in 1.3 min).
  Restored D:\a\1\s\src\Controls\src\Core.Design\Controls.Core.Design.csproj (in 18 ms).
  Restored D:\a\1\s\src\Controls\src\BindingSourceGen\Controls.BindingSourceGen.csproj (in 71 ms).
  Restored D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj (in 211 ms).
  Restored D:\a\1\s\src\Core\maps\src\Maps.csproj (in 309 ms).
  Restored D:\a\1\s\src\Controls\Maps\src\Controls.Maps.csproj (in 462 ms).
  Restored D:\a\1\s\src\TestUtils\src\DeviceTests\TestUtils.DeviceTests.csproj (in 130 ms).
  Restored D:\a\1\s\src\TestUtils\src\DeviceTests.Runners\TestUtils.DeviceTests.Runners.csproj (in 373 ms).
  Restored D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj (in 3.65 sec).
  Restored D:\a\1\s\src\Graphics\src\Graphics.Win2D\Graphics.Win2D.csproj (in 22 ms).
  Restored D:\a\1\s\src\Essentials\src\Essentials.csproj (in 75 ms).
  Restored D:\a\1\s\src\Core\tests\DeviceTests.Shared\Core.DeviceTests.Shared.csproj (in 100 ms).
  Restored D:\a\1\s\src\Core\src\Core.csproj (in 133 ms).
  Restored D:\a\1\s\src\TestUtils\src\DeviceTests.Runners.SourceGen\TestUtils.DeviceTests.Runners.SourceGen.csproj (in 4.74 sec).
C:\Users\VssAdministrator\.nuget\packages\microsoft.windowsappsdk.base\1.8.250831001\buildTransitive\Microsoft.WindowsAppSDK.SelfContained.targets(75,9): error : WindowsAppSDKSelfContained requires a supported Windows architecture. [D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj::TargetFramework=net10.0-windows10.0.19041.0]

Build FAILED.

C:\Users\VssAdministrator\.nuget\packages\microsoft.windowsappsdk.base\1.8.250831001\buildTransitive\Microsoft.WindowsAppSDK.SelfContained.targets(75,9): error : WindowsAppSDKSelfContained requires a supported Windows architecture. [D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj::TargetFramework=net10.0-windows10.0.19041.0]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:08.52

🟢 With fix — 📱 EntryTests (PasswordEntryPlatformSetDoesNotCrash): FAIL ❌ · 18s
  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Users\VssAdministrator\.nuget\packages\microsoft.windowsappsdk.base\1.8.250831001\buildTransitive\Microsoft.WindowsAppSDK.SelfContained.targets(75,9): error : WindowsAppSDKSelfContained requires a supported Windows architecture. [D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj::TargetFramework=net10.0-windows10.0.19041.0]

Build FAILED.

C:\Users\VssAdministrator\.nuget\packages\microsoft.windowsappsdk.base\1.8.250831001\buildTransitive\Microsoft.WindowsAppSDK.SelfContained.targets(75,9): error : WindowsAppSDKSelfContained requires a supported Windows architecture. [D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj::TargetFramework=net10.0-windows10.0.19041.0]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:08.13

⚠️ Issues found
  • EntryTests (PasswordEntryPlatformSetDoesNotCrash) FAILED with fix (should pass)
📁 Fix files reverted (2 files)
  • eng/pipelines/ci-copilot.yml
  • src/Core/src/Platform/Windows/MauiPasswordTextBox.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 10, 2026

🤖 AI Summary

📊 Expand Full Review3e97d6b · fixed test condition as per AI concerns.
🔍 Pre-Flight — Context & Validation

Issue: #33334 - [WinUI] Password Obfuscation causes unhandled crash
PR: #33891 - [Windows] Fix password Entry crash when setting text on empty field
Platforms Affected: Windows only
Files Changed: 1 implementation, 1 test

Key Findings

  • Crash occurs in MauiPasswordTextBox.DetermineTextFromPassword when realText is empty ("") and passwordText is non-empty. lengthDifference = passwordText.Length - 0 = N > 0, so start - lengthDifference = 0 - N = -N. In unchecked arithmetic, -N wraps to a large uint (e.g. 4294967295), causing ArgumentOutOfRangeException in String.Insert().
  • Issue confirmed by Syncfusion contributor (label s/verified). Production crash trace shows startIndex ('4294967295') must be less than or equal to '0'.
  • PR fix: Math.Max(0, start - lengthDifference) clamps the insert index to ≥ 0. Minimal one-line change in DetermineTextFromPassword.
  • Prior pr-finalize review by kubaflo (MEMBER): ✅ with minor optional suggestions (stronger assertion, indentation).
  • Prior agent review (MauiBot, April 5): Requested changes citing (1) Remove branch not guarded, (2) indentation, (3) weak assertion.
  • PR author responded: Remove branch concern dismissed — delete path only triggered via user-driven input where indices stay valid; assertion already strengthened to Assert.Equal("test", ...).
  • Gate FAILED — both "without fix" and "with fix" builds failed with WindowsAppSDKSelfContained requires a supported Windows architecture in Graphics.csproj. This is an environment/architecture issue unrelated to PR code. "Without fix" correctly failed (expected ✅); "with fix" failed unexpectedly (build error ❌).
  • One unresolved but outdated inline review comment from copilot-pull-request-reviewer about indentation at line 136. Checking actual file: line 136 has 3 tabs matching surrounding code — the suggestion appears misaligned.
  • Remove branch: realText.Remove(start, -lengthDifference) — no bounds check. PR author argues this path is safe for user-driven input. Remains a pre-existing potential concern.
  • Test assertion already strengthened: Assert.Equal("test", passwordTextBox.Text) is present in the current code.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #33891 Math.Max(0, start - lengthDifference) to clamp Insert index ⏳ PENDING (Gate env blocked) MauiPasswordTextBox.cs Logically correct; env build error blocked validation

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Early-return if (realText.Length == 0) return passwordText — short-circuit before index arithmetic ⚠️ BLOCKED MauiPasswordTextBox.cs Build env: WindowsAppSDKSelfContained requires a supported Windows architecture
2 try-fix (claude-sonnet-4.6) Math.Clamp(start - lengthDifference, 0, realText.Length) on Insert branch + Math.Clamp(start, 0, ...) on Remove branch ⚠️ BLOCKED MauiPasswordTextBox.cs Same build env blocker
3 try-fix (gpt-5.3-codex) Caller-side normalization of SelectionStart before calling DetermineTextFromPassword ⚠️ BLOCKED MauiPasswordTextBox.cs Same build env blocker
4 try-fix (gpt-5.4) Character-level merge rewrite — prefix/suffix merge eliminating Insert/Remove index arithmetic entirely ⚠️ BLOCKED MauiPasswordTextBox.cs Same build env blocker
5 try-fix (claude-opus-4.6, cross-poll) Reentrancy guard: if (_internalChangeFlag) return + if (lengthDifference > 0 && SelectionStart < lengthDifference) return in OnNativeTextChanging ⚠️ BLOCKED MauiPasswordTextBox.cs Same build env blocker
PR PR #33891 Math.Max(0, start - lengthDifference) to clamp Insert index ⚠️ BLOCKED (build env) MauiPasswordTextBox.cs Logically correct; same env blocks validation

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes Reentrancy guard _internalChangeFlag to skip DetermineTextFromPassword for programmatic changes (→ Attempt 5)
claude-sonnet-4.6 2 No NO NEW IDEAS
gpt-5.3-codex 2 Yes Range-based buffer update from change event data (same pattern as Attempt 4 rewrite)
gpt-5.4 2 Yes Set Password directly in TextBoxExtensions.UpdateText instead of Text to bypass SelectionStart path

Exhausted: Yes — all empirical testing blocked by WindowsAppSDKSelfContained requires a supported Windows architecture build environment limitation. Solution space thoroughly explored across 5 distinct fix strategies.

Selected Fix: PR's fix (Math.Max(0, start - lengthDifference)) — all 5 try-fix alternatives were blocked by the same build environment limitation. No empirical comparison was possible. The PR's fix is the simplest and most surgical. Among alternatives: Attempt 2 (Math.Clamp) is slightly more comprehensive (bounds-checks the upper end too), but unverified empirically. The PR's one-line fix directly addresses the root cause without changing method structure.


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #33334 confirmed, Windows-only crash in DetermineTextFromPassword
Gate ❌ FAILED Windows — build env error (not code): WindowsAppSDKSelfContained requires a supported Windows architecture. "Without fix" failed as expected (✅, 104s), but "with fix" also failed (❌, 18s — same build error, test never executed).
Try-Fix ✅ COMPLETE 5 attempts, 0 passing — all ⚠️ BLOCKED by same build env limitation
Report ✅ COMPLETE

Summary

PR #33891 fixes a Windows-only ArgumentOutOfRangeException crash in MauiPasswordTextBox.DetermineTextFromPassword with a minimal one-line change (Math.Max(0, start - lengthDifference)). The fix is logically correct. The Gate failed due to a build environment limitation (WindowsAppSDKSelfContained requires a supported Windows architecture in Graphics.csproj) that is unrelated to the PR code — the same error appeared in all 5 try-fix attempts. Empirical validation was not possible in this environment.

Root Cause

When a password Entry is empty (realText = "") and text is programmatically set, TextChanging fires with SelectionStart = 0. DetermineTextFromPassword("", 0, "test") computes lengthDifference = 4 and calls "".Insert(0 - 4, "●●●●")Insert(-4, ...). In unchecked arithmetic, -4 wraps to a large uint value (4294967295), causing ArgumentOutOfRangeException. The production crash trace (issue #33334) confirms startIndex ('4294967295') must be less than or equal to '0'.

Fix Quality

The Insert branch fix is logically correct and minimal. Math.Max(0, start - lengthDifference) prevents the negative index for the reported crash scenario.

Remaining issues:

  1. ⚠️ Gate failure is environmental (non-blocking): The build error in Graphics.csproj is a pre-existing CI infrastructure issue unrelated to this PR. This cannot be fixed within the PR.

  2. ⚠️ Remove branch not guarded (potential crash — same root cause class): The else if (lengthDifference < 0) branch calls realText.Remove(start, -lengthDifference) without bounds validation. The PR author argues this path is only triggered through user-driven input where indices remain valid. However, if start > realText.Length or start + (-lengthDifference) > realText.Length can occur (e.g., concurrent updates, paste operations with unusual SelectionStart), this will throw ArgumentOutOfRangeException with the same crash pattern. The PR author should either add defensive bounds checking or explain concretely why this path is safe.

  3. ℹ️ Indentation of test comment (trivial): Line 136 in EntryTests.Windows.cs — the comment indentation appears to match the surrounding code (3 tabs). The original copilot suggestion (2 tabs) appears to have been incorrect. This is not a concern.

  4. ✅ Test assertion is adequate: Assert.Equal("test", passwordTextBox.Text) verifies the text was correctly set. This was addressed by the PR author.

Selected Fix

Selected Fix: PR — it is logically sound for the reported scenario. No try-fix candidate empirically outperformed it (all blocked). Before merging, the Remove branch defensive coding should be discussed or addressed.


@kubaflo kubaflo added the s/agent-suggestions-implemented Maintainer applies when PR author adopts agent's recommendation label Apr 12, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current April 12, 2026 12:04
@kubaflo kubaflo merged commit 7a0e65b into dotnet:inflight/current Apr 12, 2026
81 of 97 checks passed
PureWeen pushed a commit that referenced this pull request Apr 14, 2026
…33891)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause
When a password `Entry` field is empty and text is programmatically set,
the obfuscation logic calculates a negative insert position `(0 - 4 =
-4)`. String. `Insert()` doesn't accept negative indices, causing an
`ArgumentOutOfRangeException` crash in windows.

### Description of Change

Added `Math.Max(0, ...)` to clamp the insert position to a minimum of 0,
preventing negative **values.**

### Issues Fixed

Fixes #33334 

### Platforms Tested

- [x] iOS
- [x] Android  
- [x] Windows
- [x] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/43993544-7700-4bff-a04c-d34b999ac962"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/e7f12e20-1cd8-45e7-b07d-bfe7ebac6248"
/> |
devanathan-vaithiyanathan pushed a commit to Tamilarasan-Paranthaman/maui that referenced this pull request Apr 21, 2026
…otnet#33891)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause
When a password `Entry` field is empty and text is programmatically set,
the obfuscation logic calculates a negative insert position `(0 - 4 =
-4)`. String. `Insert()` doesn't accept negative indices, causing an
`ArgumentOutOfRangeException` crash in windows.

### Description of Change

Added `Math.Max(0, ...)` to clamp the insert position to a minimum of 0,
preventing negative **values.**

### Issues Fixed

Fixes dotnet#33334 

### Platforms Tested

- [x] iOS
- [x] Android  
- [x] Windows
- [x] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/43993544-7700-4bff-a04c-d34b999ac962"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/e7f12e20-1cd8-45e7-b07d-bfe7ebac6248"
/> |
PureWeen pushed a commit that referenced this pull request Apr 22, 2026
…33891)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause
When a password `Entry` field is empty and text is programmatically set,
the obfuscation logic calculates a negative insert position `(0 - 4 =
-4)`. String. `Insert()` doesn't accept negative indices, causing an
`ArgumentOutOfRangeException` crash in windows.

### Description of Change

Added `Math.Max(0, ...)` to clamp the insert position to a minimum of 0,
preventing negative **values.**

### Issues Fixed

Fixes #33334 

### Platforms Tested

- [x] iOS
- [x] Android  
- [x] Windows
- [x] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/43993544-7700-4bff-a04c-d34b999ac962"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/e7f12e20-1cd8-45e7-b07d-bfe7ebac6248"
/> |
PureWeen pushed a commit that referenced this pull request Apr 28, 2026
…33891)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause
When a password `Entry` field is empty and text is programmatically set,
the obfuscation logic calculates a negative insert position `(0 - 4 =
-4)`. String. `Insert()` doesn't accept negative indices, causing an
`ArgumentOutOfRangeException` crash in windows.

### Description of Change

Added `Math.Max(0, ...)` to clamp the insert position to a minimum of 0,
preventing negative **values.**

### Issues Fixed

Fixes #33334 

### Platforms Tested

- [x] iOS
- [x] Android  
- [x] Windows
- [x] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/43993544-7700-4bff-a04c-d34b999ac962"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/e7f12e20-1cd8-45e7-b07d-bfe7ebac6248"
/> |
PureWeen pushed a commit that referenced this pull request Apr 29, 2026
…33891)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause
When a password `Entry` field is empty and text is programmatically set,
the obfuscation logic calculates a negative insert position `(0 - 4 =
-4)`. String. `Insert()` doesn't accept negative indices, causing an
`ArgumentOutOfRangeException` crash in windows.

### Description of Change

Added `Math.Max(0, ...)` to clamp the insert position to a minimum of 0,
preventing negative **values.**

### Issues Fixed

Fixes #33334 

### Platforms Tested

- [x] iOS
- [x] Android  
- [x] Windows
- [x] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/43993544-7700-4bff-a04c-d34b999ac962"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/e7f12e20-1cd8-45e7-b07d-bfe7ebac6248"
/> |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-entry Entry community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/windows s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) s/agent-suggestions-implemented Maintainer applies when PR author adopts agent's recommendation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WinUI] Password Obfuscation causes unhandled crash

6 participants