spectreconsole/spectre.console

IndexOutOfRangeException thrown by AnsiConsoleExtensions.WriteException if no stack trace

Closed this issue ยท 7 comments

Information

  • OS: Any
  • Version: 0.50.0
  • Terminal: N/A

Describe the bug

If an exception with no stack trace is passed to AnsiConsoleExtensions.WriteException(), then an IndexOutOfRangeException is thrown:

System.IndexOutOfRangeException
  HResult=0x80131508
  Message=Index was outside the bounds of the array.
  Source=System.Private.CoreLib
  StackTrace:
   at Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowIndexOutOfRangeException()
   at Spectre.Console.ExceptionFormatter.GetStackFrames(Exception ex, ExceptionSettings settings)
   at Spectre.Console.ExceptionFormatter.GetException(Exception exception, ExceptionSettings settings)
   at Spectre.Console.ExceptionFormatter.Format(Exception exception, ExceptionSettings settings)
   at Spectre.Console.ExceptionExtensions.GetRenderable(Exception exception, ExceptionSettings settings)
   at Spectre.Console.ExceptionExtensions.GetRenderable(Exception exception, ExceptionFormats format)
   at Spectre.Console.AnsiConsoleExtensions.WriteException(IAnsiConsole console, Exception exception, ExceptionFormats format)
   at MartinCostello.DotNetBumper.IAnsiConsoleExtensions.WriteExceptionLine(IAnsiConsole console, String message, Exception exception) in D:\Coding\martincostello\dotnet-bumper\src\DotNetBumper.Core\IAnsiConsoleExtensions.cs:line 115
   at MartinCostello.DotNetBumper.IAnsiConsoleExtensionsTests.<>c__DisplayClass4_0.<WriteExceptionLine_Does_Not_Throw>b__0() in D:\Coding\martincostello\dotnet-bumper\tests\DotNetBumper.Tests\IAnsiConsoleExtensionsTests.cs:line 76
   at Shouldly.Should.NotThrowInternal(Action action, String customMessage, String shouldlyMethod)

I found this as I'd written a test to test an extension method I'd written (below) and I just create an exception and pass it in to verify no exception is thrown, and with dependabot's PR to update my code to 0.50.0, that test now fails:

public static void WriteExceptionLine(this IAnsiConsole console, string message, Exception exception)
{
    console.WriteErrorLine(message);
    console.WriteException(exception);
}

[Fact]
public static void WriteExceptionLine_Does_Not_Throw()
{
    // Arrange
    var console = Substitute.For<IAnsiConsole>();

    // Act and Assert
    Should.NotThrow(() => console.WriteExceptionLine("An error.", new InvalidOperationException("An exception.")));
}

To Reproduce

[Fact]
public static void Repro()
{
    var console = Substitute.For<IAnsiConsole>();

    Should.NotThrow(() => console.WriteException(new InvalidOperationException("An exception.")));
}

Expected behavior

No exception is thrown.


Please upvote ๐Ÿ‘ this issue if you are interested in it.

Looks like the exception comes from here where there's no bounds check:

@martincostello Ah, looks like a regression. I'll take a look at it tomorrow and push a patch release. Thanks for reporting this!

@patriksvensson Happy to do a PR for this today if you haven't already started on it - should be simple enough.

I was hit by this: ErikEJ/SqlServer.Rules#226 - is the fix in the latest preview on NuGet?

@ErikEJ Yes, it should be. We will soon release 0.51 as well.

@patriksvensson Thanks. I have reverted to 0.49.1 in the meantime, will just update when 0.51 arrives

Any chance of a stable 0.5.1 with the fix soon? ๐Ÿ˜ƒ