Description
Description
You use RangeAttribute
like this, to indicate a minimum and maximum value for data annotation:
[Range(-50, 50)]
public string Value { get; set; }
If you try to pass a value that is not an integer, or doesn’t fall between [-50, 50], IsValid()
correctly returns false.
However, if you pass a numerical value that falls outside the bounds of the type (e.g. 2147483648L which exceeds the maximum value of int), then you get an uncaught exception:
System.OverflowException: Value was either too large or too small for an Int32.
at System.Number.ThrowOverflowException[TInteger]()
at System.String.System.IConvertible.ToInt32(IFormatProvider provider)
at System.ComponentModel.DataAnnotations.RangeAttribute.<>c.<SetupConversion>b__37_0(Object v)
at System.ComponentModel.DataAnnotations.RangeAttribute.IsValid(Object value)
at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value, ValidationContext validationContext)
The try/catch
block in RangeAttribute:IsValid()
should handle all exceptions by returning false, not just a selected few exception types.
Reproduction Steps
var rangeAttribute = new RangeAttribute(-50, 50);
rangeAttribute.IsValid(2147483648L); // throws OverflowException instead of returning false
Expected behavior
Any failure in IsValid() should return false.
Actual behavior
Some failures in IsValid() result in an unhandled exception.
Regression?
Unknown
Known Workarounds
You can subclass RangeAttribute, override IsValid(), and wrap the call to base.IsValid() in an exception handler:
public class CorrectedRangeAttribute : RangeAttribute
{
public CorrectedRangeAttribute(double minimum, double maximum) : base(minimum, maximum)
{
}
public CorrectedRangeAttribute(int minimum, int maximum) : base(minimum, maximum)
{
}
public CorrectedRangeAttribute(Type type, string minimum, string maximum) : base(type, minimum, maximum)
{
}
public override bool IsValid(object value)
{
try
{
return base.IsValid(value);
}
catch
{
return false;
}
}
}
Configuration
- net8.0, net9.0
- Windows 11 Enterprise 23H2
- x64
- This is a code problem, not an execution environment problem
- N/A
Other information
The problem is in runtime/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations /RangeAttribute.cs
in the function public override bool IsValid(object? value)
where there is no final catch
in the try/catch
block.
This allows uncaught exceptions to flow out of a function which should always return either true or false.