diff --git a/src/FluentValidation.Tests/ExclusiveBetweenValidatorTests.cs b/src/FluentValidation.Tests/ExclusiveBetweenValidatorTests.cs index a4ebfa4..6cb332f 100644 --- a/src/FluentValidation.Tests/ExclusiveBetweenValidatorTests.cs +++ b/src/FluentValidation.Tests/ExclusiveBetweenValidatorTests.cs @@ -127,6 +127,13 @@ public class ExclusiveBetweenValidatorTests { Assert.Throws(() => RangeValidatorFactory.CreateExclusiveBetween("ccc", "aaa")); } + [Fact] + public void When_the_to_is_smaller_than_the_from_then_the_validator_should_throw_for_chars() { + // char.CompareTo returns the arithmetic difference (for example 'a'.CompareTo('c') == -2), + // so the range guard must treat any negative result as "less than", not only -1. + Assert.Throws(() => RangeValidatorFactory.CreateExclusiveBetween('c', 'a')); + } + [Fact] public void When_the_validator_fails_the_error_message_should_be_set_for_strings() { var validator = new TestValidator(v => v.RuleFor(x => x.Surname).ExclusiveBetween("bbb", "zzz")); diff --git a/src/FluentValidation.Tests/InclusiveBetweenValidatorTests.cs b/src/FluentValidation.Tests/InclusiveBetweenValidatorTests.cs index 8341b18..3f1cc76 100644 --- a/src/FluentValidation.Tests/InclusiveBetweenValidatorTests.cs +++ b/src/FluentValidation.Tests/InclusiveBetweenValidatorTests.cs @@ -122,6 +122,13 @@ public class InclusiveBetweenValidatorTests { Assert.Throws(() => RangeValidatorFactory.CreateInclusiveBetween("ccc", "aaa")); } + [Fact] + public void When_the_to_is_smaller_than_the_from_then_the_validator_should_throw_for_chars() { + // char.CompareTo returns the arithmetic difference (for example 'a'.CompareTo('c') == -2), + // so the range guard must treat any negative result as "less than", not only -1. + Assert.Throws(() => RangeValidatorFactory.CreateInclusiveBetween('c', 'a')); + } + [Fact] public void When_the_validator_fails_the_error_message_should_be_set_for_strings() { var validator = new TestValidator(v => v.RuleFor(x => x.Surname).InclusiveBetween("bbb", "zzz")); diff --git a/src/FluentValidation/Validators/RangeValidator.cs b/src/FluentValidation/Validators/RangeValidator.cs index eafe717..28acc8f 100644 --- a/src/FluentValidation/Validators/RangeValidator.cs +++ b/src/FluentValidation/Validators/RangeValidator.cs @@ -34,7 +34,11 @@ public abstract class RangeValidator : PropertyValidator.Compare only guarantees the sign of the result, not a specific + // magnitude, so any negative value means "to" is less than "from". Comparing against + // -1 misses comparers that return other negatives (for example char.CompareTo, which + // returns the arithmetic difference, or custom comparers). + if (comparer.Compare(to, from) < 0) { throw new ArgumentOutOfRangeException(nameof(to), "To should be larger than from."); } }