Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 23, 2025

Fix RangeAttribute to handle OverflowException

Summary

Fixed RangeAttribute.IsValid() to catch OverflowException and return false instead of throwing an uncaught exception when values exceed the bounds of the operand type.

Changes Made

  • Added catch for OverflowException in RangeAttribute.IsValid()
  • Added catch for OverflowException in Emitter.cs source generator (2 locations)
  • Updated test to verify overflow values return false instead of throwing
  • Added test cases for long values exceeding int.MaxValue and int.MinValue
  • Updated 10 source generator baseline test files (8 in SourceGeneration.Unit.Tests + 2 in SourceGenerationTests)
  • All tests pass (872 tests in System.ComponentModel.Annotations, 69 tests in SourceGeneration.Unit.Tests, 60 tests in SourceGenerationTests)
  • CodeQL security check passed

Issue Resolution

The issue reported that passing values like 2147483648L (exceeds int.MaxValue) to RangeAttribute(-50, 50) threw OverflowException instead of returning false. This fix ensures IsValid() properly catches OverflowException during type conversion and returns false as expected.

Files Changed

  1. RangeAttribute.cs - Added OverflowException catch block
  2. Emitter.cs - Added OverflowException to catch filter (2 locations)
  3. RangeAttributeTests.cs - Updated test expectations and added overflow test cases
  4. 10 baseline test files - Updated expected generated code to include OverflowException
Original prompt

This section details on the original issue you should resolve

<issue_title>RangeAttribute throws exception if value is outside range of type</issue_title>
<issue_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.</issue_description>

Comments on the Issue (you are @copilot in this section)

@tarekgh @BillVanArk you can easily workaround this by doing
[Range(-50L, 50L)]

This forces the use of long numbers, which should preserve the correct behavior.

Also, if you are interested, you can submit a PR to fix the issue in the code

Just catch the overflow exception there. We'll need to fix the options source gen too

catch (global::System.Exception e) when (e is global::System.FormatException or global::System.InvalidCastException or global::System.NotSupportedException)
</comment_new>

Fixes #115982


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

- Added catch for OverflowException in RangeAttribute.IsValid()
- Added catch for OverflowException in Emitter.cs source generator
- Updated and added tests to verify overflow values return false
- Changed test expectation from throwing to returning false

Co-authored-by: stephentoub <[email protected]>
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-componentmodel-dataannotations
See info in area-owners.md if you want to be subscribed.

Updated all 8 baseline test files to include OverflowException in
the catch clause, matching the generator changes made in Emitter.cs

Co-authored-by: stephentoub <[email protected]>
Copilot AI changed the title [WIP] Fix RangeAttribute exception for out-of-range values Fix RangeAttribute to catch OverflowException instead of throwing Oct 23, 2025
Copilot AI requested a review from stephentoub October 23, 2025 19:21
Copilot finished work on behalf of stephentoub October 23, 2025 19:21
@stephentoub
Copy link
Member

@copilot, this is failing tests:

  Discovering: Microsoft.Extensions.Options.SourceGeneration.Tests (method display = ClassAndMethod, method display options = None)
  Discovered:  Microsoft.Extensions.Options.SourceGeneration.Tests (found 54 test cases)
  Starting:    Microsoft.Extensions.Options.SourceGeneration.Tests (parallel test collections = on [2 threads], stop on fail = off)
    Microsoft.Gen.OptionsValidation.Test.EmitterTests.TestEmitter [FAIL]
      Assert.Equal() Failure: Strings differ
                                        ↓ (pos 163798)
      Expected: ···"otSupportedException)\n                {\n "···
      Actual:   ···"otSupportedException or global::System.Ov"···
                                        ↑ (pos 163798)
      Stack Trace:
        /_/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs(56,0): at Microsoft.Gen.OptionsValidation.Test.EmitterTests.TestEmitter()
        --- End of stack trace from previous location ---
  Finished:    Microsoft.Extensions.Options.SourceGeneration.Tests
=== TEST EXECUTION SUMMARY ===
   Microsoft.Extensions.Options.SourceGeneration.Tests  Total: 60, Errors: 0, Failed: 1, Skipped: 0, Time: 2.715s

@stephentoub stephentoub marked this pull request as ready for review October 23, 2025 21:15
Copilot AI review requested due to automatic review settings October 23, 2025 21:15
Copy link
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 bug where RangeAttribute.IsValid() throws an uncaught OverflowException instead of returning false when validating values that exceed the bounds of the operand type (e.g., a long value exceeding int.MaxValue).

Key changes:

  • Added OverflowException to the exception handling in RangeAttribute.IsValid()
  • Updated source generator to include OverflowException in generated validation code
  • Modified tests to expect false return value instead of thrown exceptions for overflow scenarios

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
RangeAttribute.cs Added catch block for OverflowException to return false instead of propagating the exception
Emitter.cs Updated source generator exception filters to include OverflowException in two locations
RangeAttributeTests.cs Changed test expectations from throwing exception to returning false, added new test cases for overflow values
OptionsExtendingSystemClassTest.netfx.g.cs Updated baseline with new exception filter
OptionsExtendingSystemClassTest.netcore.g.cs Updated baseline with new exception filter
GeneratedAttributesTest.netfx.lang11.g.cs Updated baseline with new exception filter
GeneratedAttributesTest.netfx.lang10.g.cs Updated baseline with new exception filter
GeneratedAttributesTest.netcore.lang11.g.cs Updated baseline with new exception filter
GeneratedAttributesTest.netcore.lang10.g.cs Updated baseline with new exception filter
EmitterWithCustomValidator.netfx.g.cs Updated baseline with new exception filter
EmitterWithCustomValidator.netcore.g.cs Updated baseline with new exception filter

Updated the two additional baseline files (NetCoreApp and NetFX Validators.g.cs)
that were missed in the previous commit to include OverflowException in the
catch clause.

Co-authored-by: stephentoub <[email protected]>
Copy link
Contributor Author

Copilot AI commented Oct 23, 2025

@copilot, this is failing tests:

  Discovering: Microsoft.Extensions.Options.SourceGeneration.Tests (method display = ClassAndMethod, method display options = None)

...

Fixed in commit 23b1940. Updated the two missing baseline files (NetCoreApp/Validators.g.cs and NetFX/Validators.g.cs) to include OverflowException. All tests now pass.

Copilot finished work on behalf of stephentoub October 23, 2025 21:40
@tarekgh
Copy link
Member

tarekgh commented Oct 24, 2025

/ba-g debug and AOT legs timed out, unrelated to the change.

@tarekgh tarekgh merged commit 8a293ea into main Oct 24, 2025
78 of 85 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RangeAttribute throws exception if value is outside range of type

3 participants