From 300c999c96eabcbe661242e247833568f3a5a3dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Nov 2025 21:08:42 +0000 Subject: [PATCH 1/8] Fix IndexOutOfRangeException in ILVerify for invalid exception handler offsets Co-authored-by: agocke <515774+agocke@users.noreply.github.com> Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../tools/Common/TypeSystem/IL/ILImporter.cs | 36 +++++++++++-- .../ILTests/ExceptionRegionTests.il | 50 +++++++++++++++++++ .../ILTests/ExceptionRegionTests.ilproj | 1 + .../tools/ILVerification/ILImporter.Verify.cs | 10 +++- src/coreclr/tools/ILVerification/Strings.resx | 3 ++ .../tools/ILVerification/VerifierError.cs | 4 +- .../IL/ILImporter.Scanner.cs | 5 ++ 7 files changed, 101 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index 74da13d94a398e..8da2e0afc67963 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -276,10 +276,40 @@ private void FindEHTargets() { var r = _exceptionRegions[i]; - CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; + // Check try region bounds (avoiding integer overflow) + if ((uint)r.ILRegion.TryOffset >= (uint)_basicBlocks.Length || + (uint)r.ILRegion.TryLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.TryOffset) + { + ReportInvalidExceptionRegion(); + } + else + { + CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; + } + + // Check filter region bounds (for filter exception handlers) if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) - CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; - CreateBasicBlock(r.ILRegion.HandlerOffset).HandlerStart = true; + { + if ((uint)r.ILRegion.FilterOffset >= (uint)_basicBlocks.Length) + { + ReportInvalidExceptionRegion(); + } + else + { + CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; + } + } + + // Check handler region bounds (avoiding integer overflow) + if ((uint)r.ILRegion.HandlerOffset >= (uint)_basicBlocks.Length || + (uint)r.ILRegion.HandlerLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.HandlerOffset) + { + ReportInvalidExceptionRegion(); + } + else + { + CreateBasicBlock(r.ILRegion.HandlerOffset).HandlerStart = true; + } } } diff --git a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il index 874c4202a0e8a6..d5eb26afff0ae9 100644 --- a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il +++ b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il @@ -764,4 +764,54 @@ throw ret } + + .method public hidebysig instance void TryOffset.ExceedsCodeSize_Invalid_EHClauseOutOfRange() cil managed + { + .maxstack 1 + + ret + // Try region starts at offset 1000 which is beyond code size (code size is 1) + .try 1000 to 1001 catch [System.Runtime]System.Exception handler 0 to 1 + } + + .method public hidebysig instance void HandlerOffset.ExceedsCodeSize_Invalid_EHClauseOutOfRange() cil managed + { + .maxstack 1 + + ret + // Handler region starts at offset 1000 which is beyond code size (code size is 1) + .try 0 to 1 catch [System.Runtime]System.Exception handler 1000 to 1001 + } + + .method public hidebysig instance void FilterOffset.ExceedsCodeSize_Invalid_EHClauseOutOfRange() cil managed + { + .maxstack 1 + + ldc.i4.0 + endfilter + leave.s IL_0004 + IL_0004: ret + // Filter region starts at offset 1000 which is beyond code size (code size is 5) + .try 0 to 2 filter 1000 handler 2 to 4 + } + + .method public hidebysig instance void TryEndOffset.ExceedsCodeSize_Invalid_EHClauseOutOfRange() cil managed + { + .maxstack 1 + + nop + ret + // Try region ends at offset 1000 which is beyond code size (code size is 2) + .try 0 to 1000 catch [System.Runtime]System.Exception handler 1 to 2 + } + + .method public hidebysig instance void HandlerEndOffset.ExceedsCodeSize_Invalid_EHClauseOutOfRange() cil managed + { + .maxstack 1 + + nop + ret + // Handler region ends at offset 1000 which is beyond code size (code size is 2) + .try 0 to 1 catch [System.Runtime]System.Exception handler 1 to 1000 + } } diff --git a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj index 356b4dcc778989..6918de85f055d5 100644 --- a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj +++ b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj @@ -1,6 +1,7 @@ $(MSBuildProjectName) + $(IlasmFlags) -ERR diff --git a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs index 434d2ab7687b38..a8dd3c939b39f1 100644 --- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs +++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs @@ -209,6 +209,9 @@ public ILImporter(MethodDesc method, MethodIL methodIL) public void Verify() { + // Check code size before any other processing + FatalCheck(_ilBytes.Length > 0, VerifierError.CodeSizeZero); + _instructionBoundaries = new bool[_ilBytes.Length]; FindBasicBlocks(); @@ -286,8 +289,6 @@ private void FindEnclosingExceptionRegions() /// private void InitialPass() { - FatalCheck(_ilBytes.Length > 0, VerifierError.CodeSizeZero); - _modifiesThisPtr = false; _validTargetOffsets = new bool[_ilBytes.Length]; @@ -2823,6 +2824,11 @@ void ReportInvalidInstruction(ILOpcode opcode) VerificationError(VerifierError.UnknownOpcode); } + void ReportInvalidExceptionRegion() + { + VerificationError(VerifierError.EHClauseOutOfRange); + } + // // Deprecated // diff --git a/src/coreclr/tools/ILVerification/Strings.resx b/src/coreclr/tools/ILVerification/Strings.resx index 9f26f996d62f55..02be5d1e00ff0c 100644 --- a/src/coreclr/tools/ILVerification/Strings.resx +++ b/src/coreclr/tools/ILVerification/Strings.resx @@ -297,6 +297,9 @@ Fall through end of the method without returning. + + Exception handling clause bounds outside code size. + Cannot construct an instance of abstract class. diff --git a/src/coreclr/tools/ILVerification/VerifierError.cs b/src/coreclr/tools/ILVerification/VerifierError.cs index 2d237aa9c5b083..bc4821fbedb7d4 100644 --- a/src/coreclr/tools/ILVerification/VerifierError.cs +++ b/src/coreclr/tools/ILVerification/VerifierError.cs @@ -32,9 +32,7 @@ public enum VerifierError MethodFallthrough, // Fall through end of the method without returning. //E_TRY_GTEQ_END "try start >= try end." - //E_TRYEND_GT_CS "try end > code size." //E_HND_GTEQ_END "handler start >= handler end." - //E_HNDEND_GT_CS "handler end > code size." //E_TRY_START "Try starts in the middle of an instruction." //E_HND_START "Handler starts in the middle of an instruction." //E_TRY_OVERLAP "Try block overlap with another block." @@ -44,7 +42,7 @@ public enum VerifierError //E_FIL_CONT_TRY "Filter contains try." //E_FIL_CONT_HND "Filter contains handler." //E_FIL_CONT_FIL "Nested filters." - //E_FIL_GTEQ_CS "filter >= code size." + EHClauseOutOfRange, // Exception handling clause bounds outside code size. FallthroughException, // Fallthrough the end of an exception block. FallthroughIntoHandler, // Fallthrough into an exception handler. FallthroughIntoFilter, // Fallthrough into an exception filter. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index 4394d08ad8240b..0def891ca89bc0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -1627,6 +1627,11 @@ private static void ReportInvalidInstruction(ILOpcode opcode) ThrowHelper.ThrowInvalidProgramException(); } + private static void ReportInvalidExceptionRegion() + { + ThrowHelper.ThrowInvalidProgramException(); + } + private static bool IsTypeGetTypeFromHandle(MethodDesc method) { if (method.IsIntrinsic && method.Name.SequenceEqual("GetTypeFromHandle"u8)) From a6c761ad42a194f30e75572a2dee643bbe13292f Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 16 May 2026 19:07:21 -0700 Subject: [PATCH 2/8] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/coreclr/tools/ILVerification/ILImporter.Verify.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs index a8dd3c939b39f1..135f7f3b1d1825 100644 --- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs +++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs @@ -2827,6 +2827,7 @@ void ReportInvalidInstruction(ILOpcode opcode) void ReportInvalidExceptionRegion() { VerificationError(VerifierError.EHClauseOutOfRange); + AbortMethodVerification(); } // From dfa48be60d4ab4a6692a7201bc6cca3513366281 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 16 May 2026 19:22:25 -0700 Subject: [PATCH 3/8] Apply suggestions from code review Co-authored-by: Jan Kotas --- .../tools/Common/TypeSystem/IL/ILImporter.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index 8da2e0afc67963..10084a750d7859 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -282,10 +282,7 @@ private void FindEHTargets() { ReportInvalidExceptionRegion(); } - else - { - CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; - } + CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; // Check filter region bounds (for filter exception handlers) if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) @@ -294,10 +291,7 @@ private void FindEHTargets() { ReportInvalidExceptionRegion(); } - else - { - CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; - } + CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; } // Check handler region bounds (avoiding integer overflow) @@ -306,10 +300,7 @@ private void FindEHTargets() { ReportInvalidExceptionRegion(); } - else - { - CreateBasicBlock(r.ILRegion.HandlerOffset).HandlerStart = true; - } + CreateBasicBlock(r.ILRegion.HandlerOffset).HandlerStart = true; } } From 569acb0d38986d8174e74808029621d50890fd70 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 02:31:05 +0000 Subject: [PATCH 4/8] Report EH out-of-range only once per clause Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/550fcf23-f926-45ce-b6a3-249694802605 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../tools/Common/TypeSystem/IL/ILImporter.cs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index 10084a750d7859..98d1528a184a33 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -275,30 +275,31 @@ private void FindEHTargets() for (int i = 0; i < _exceptionRegions.Length; i++) { var r = _exceptionRegions[i]; - - // Check try region bounds (avoiding integer overflow) - if ((uint)r.ILRegion.TryOffset >= (uint)_basicBlocks.Length || - (uint)r.ILRegion.TryLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.TryOffset) - { - ReportInvalidExceptionRegion(); - } - CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; + bool hasOutOfRangeBounds = + (uint)r.ILRegion.TryOffset >= (uint)_basicBlocks.Length || + (uint)r.ILRegion.TryLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.TryOffset; // Check filter region bounds (for filter exception handlers) if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) { - if ((uint)r.ILRegion.FilterOffset >= (uint)_basicBlocks.Length) - { - ReportInvalidExceptionRegion(); - } - CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; + hasOutOfRangeBounds |= (uint)r.ILRegion.FilterOffset >= (uint)_basicBlocks.Length; } // Check handler region bounds (avoiding integer overflow) - if ((uint)r.ILRegion.HandlerOffset >= (uint)_basicBlocks.Length || - (uint)r.ILRegion.HandlerLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.HandlerOffset) + hasOutOfRangeBounds |= + (uint)r.ILRegion.HandlerOffset >= (uint)_basicBlocks.Length || + (uint)r.ILRegion.HandlerLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.HandlerOffset; + + if (hasOutOfRangeBounds) { ReportInvalidExceptionRegion(); + continue; + } + CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; + + if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) + { + CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; } CreateBasicBlock(r.ILRegion.HandlerOffset).HandlerStart = true; } From 07fda7eae020f83ea0a10faaae1d4a20e743a85c Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 16 May 2026 20:42:09 -0700 Subject: [PATCH 5/8] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index 98d1528a184a33..c7132fb1f338a9 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -295,8 +295,8 @@ private void FindEHTargets() ReportInvalidExceptionRegion(); continue; } - CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; + CreateBasicBlock(r.ILRegion.TryOffset).TryStart = true; if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) { CreateBasicBlock(r.ILRegion.FilterOffset).FilterStart = true; From 7d01abb4f8357ac9d9741cae54ddf365f6bced64 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 16 May 2026 20:43:15 -0700 Subject: [PATCH 6/8] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index c7132fb1f338a9..a388902881a24c 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -275,17 +275,16 @@ private void FindEHTargets() for (int i = 0; i < _exceptionRegions.Length; i++) { var r = _exceptionRegions[i]; + bool hasOutOfRangeBounds = (uint)r.ILRegion.TryOffset >= (uint)_basicBlocks.Length || (uint)r.ILRegion.TryLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.TryOffset; - // Check filter region bounds (for filter exception handlers) if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) { hasOutOfRangeBounds |= (uint)r.ILRegion.FilterOffset >= (uint)_basicBlocks.Length; } - // Check handler region bounds (avoiding integer overflow) hasOutOfRangeBounds |= (uint)r.ILRegion.HandlerOffset >= (uint)_basicBlocks.Length || (uint)r.ILRegion.HandlerLength > (uint)_basicBlocks.Length - (uint)r.ILRegion.HandlerOffset; From 00aed450fffb1684c7ef55e3213af31561fb7935 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 04:06:54 +0000 Subject: [PATCH 7/8] Fix filter EH bounds check and add regression IL test Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/8021883d-2a4a-4cff-8a17-b51cfde1d7c6 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../tools/Common/TypeSystem/IL/ILImporter.cs | 4 +++- .../ILTests/ExceptionRegionTests.il | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index a388902881a24c..c1d46c98ac8d08 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -282,7 +282,9 @@ private void FindEHTargets() if (r.ILRegion.Kind == ILExceptionRegionKind.Filter) { - hasOutOfRangeBounds |= (uint)r.ILRegion.FilterOffset >= (uint)_basicBlocks.Length; + hasOutOfRangeBounds |= + (uint)r.ILRegion.FilterOffset >= (uint)_basicBlocks.Length || + (uint)r.ILRegion.FilterOffset >= (uint)r.ILRegion.HandlerOffset; } hasOutOfRangeBounds |= diff --git a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il index d5eb26afff0ae9..8b5cd632c754b1 100644 --- a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il +++ b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il @@ -814,4 +814,17 @@ // Handler region ends at offset 1000 which is beyond code size (code size is 2) .try 0 to 1 catch [System.Runtime]System.Exception handler 1 to 1000 } + + .method public hidebysig instance void FilterOffset.NotBeforeHandlerOffset_Invalid_EHClauseOutOfRange() cil managed + { + .maxstack 1 + + ldc.i4.0 + endfilter + leave.s IL_0004 + IL_0004: ret + // Filter region starts at the same offset as handler region. + .try 0 to 2 filter 2 handler 2 to 4 + } + } From 310ae3c8740fe28971fcacae7b487c6b671024cb Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 16 May 2026 21:13:04 -0700 Subject: [PATCH 8/8] Apply suggestion from @jkotas --- .../tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il index 8b5cd632c754b1..9a31ae3a928f42 100644 --- a/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il +++ b/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il @@ -826,5 +826,4 @@ // Filter region starts at the same offset as handler region. .try 0 to 2 filter 2 handler 2 to 4 } - }