diff --git a/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.Windows.cs b/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.Windows.cs index d86cb99da135..61118bec0daf 100644 --- a/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.Windows.cs +++ b/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.Windows.cs @@ -112,5 +112,31 @@ await InvokeOnMainThreadAsync(() => Assert.Equal(new string('●', entry.Text.Length), passwordTextBox.Text); }); } + + [Fact] + [Description("Password entry should not crash when platform text is set from empty")] + public async Task PasswordEntryPlatformSetDoesNotCrash() + { + var entry = new Entry + { + Text = string.Empty, + IsPassword = true + }; + + var handler = await CreateHandlerAsync(entry); + + await InvokeOnMainThreadAsync(() => + { + var platformControl = GetPlatformControl(handler); + var passwordTextBox = platformControl as Microsoft.Maui.Platform.MauiPasswordTextBox; + + Assert.NotNull(passwordTextBox); + Assert.True(passwordTextBox.IsPassword); + + // Setting Text on an empty password entry triggers TextChanging event which previously threw ArgumentOutOfRangeException + passwordTextBox.Text = "test"; + Assert.Equal("test", passwordTextBox.Text); + }); + } } } diff --git a/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs b/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs index b68052c54995..d4be871d62f6 100644 --- a/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs +++ b/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs @@ -328,7 +328,7 @@ static string DetermineTextFromPassword(string realText, int start, string passw var lengthDifference = passwordText.Length - realText.Length; if (lengthDifference > 0) - realText = realText.Insert(start - lengthDifference, new string(ObfuscationCharacter, lengthDifference)); + realText = realText.Insert(Math.Max(0, start - lengthDifference), new string(ObfuscationCharacter, lengthDifference)); else if (lengthDifference < 0) realText = realText.Remove(start, -lengthDifference);