Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.0.100-preview.7.24375.12] Markdig nuget package thrown "The parser is in an invalid infinite loop while trying to parse inlines for block..." exception when parsering markdown string to html #105792

Closed
1 task done
Junjun-zhao opened this issue Jul 30, 2024 · 16 comments · Fixed by #106229
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI blocking-release in-pr There is an active PR which will close this issue when it is merged Priority:2 Work that is important, but not critical for the release regression-from-last-release
Milestone

Comments

@Junjun-zhao
Copy link
Member

Junjun-zhao commented Jul 30, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When running 3rd part application with the latest .NET 9 build, BlazorStrap and Blog apps failed load page content during switching pages in applications. And the command prompt window throws "The parser is in an invalid infinite loop while trying to parse inlines for block [ParagraphBlock] at position ($0, 0, 0-107" exception.

Application Name: BlazorStrap, Blog, OpenBullet2
OS: Windows 10 21H2
CPU: X64
.NET Build Number: dotnet-sdk-9.0.100-preview.7.24375.12
App or App Source checking at: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2174456

Github Link:
https://github.com/chanan/BlazorStrap
https://github.com/sagebind/blog

Verify Scenarios:
1). Windows 10 21H2 AMD64 + dotnet-sdk-8.0.303: Pass
2). Windows 10 21H2 AMD64 + dotnet-sdk-9.0.100-preview.7.24371.4: Pass
3). Windows 10 21H2 AMD64 + dotnet-sdk-9.0.100-preview.7.24375.12: Fail

Expected Behavior

Switch back from "Shared Parameters" to "Contribute" successfully.
image

Steps To Reproduce

The machine has dotnet-sdk-9.0.100-preview.7.24375.12 installed.

  1. Copy BlazorStrap app from the location mentioned in the devdiv bug.
  2. Change the "BlazorStrap.Server.runtimeconfig.json" file to let the app run against with dotnet-sdk-dotnet-sdk-9.0.100-preview.7.24375.12.
    "frameworks": [
    {
    "name": "Microsoft.NETCore.App",
    "version": "9.0.0-preview.7.24374.12"
    },
    {
    "name": "Microsoft.AspNetCore.App",
    "version": "9.0.0-preview.7.24373.9"
    }
    ],
  3. Launch BlazorStrap.Server.exe.
  4. Access http://localhost:5000/ from browser.
  5. Click "Contribute" menu.
  6. Click "Shared Parameters" menu.
  7. Click "Contribute" menu.

Exceptions (if any)

Actual Result:
Switch back from "Shared Parameters" to "Contribute" failed.
image

Stack Trace from Command Prompt:

Unhandled exception rendering component: The parser is in an invalid infinite loop while trying to parse inlines for block [HeadingBlock] at position ($0, 0, 0-19
      System.InvalidOperationException: The parser is in an invalid infinite loop while trying to parse inlines for block [HeadingBlock] at position ($0, 0, 0-19
         at Markdig.Helpers.ThrowHelper.InvalidOperationException(String message)
         at Markdig.Parsers.InlineProcessor.ProcessInlineLeaf(LeafBlock leafBlock)
         at Markdig.Parsers.MarkdownParser.ProcessInlines(InlineProcessor inlineProcessor, MarkdownDocument document)
         at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline, MarkdownParserContext context)
         at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline, MarkdownParserContext context)
         at BlazorStrap_Docs.Helper.MarkdownToComponent.BuildRenderTree(RenderTreeBuilder builder) in C:\Users\v-zhiyang\Desktop\YOURSELF\BlazorStrap\src\BlazorStrap-Docs\Helper\MarkdownToComponent.cs:line 93
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
      Unhandled exception in circuit 'cwy0vMhNv_dIuMXmt46dyA7Bj5ivmQY-xXaGYDTlK6s'.
      System.InvalidOperationException: The parser is in an invalid infinite loop while trying to parse inlines for block [HeadingBlock] at position ($0, 0, 0-19
         at Markdig.Helpers.ThrowHelper.InvalidOperationException(String message)
         at Markdig.Parsers.InlineProcessor.ProcessInlineLeaf(LeafBlock leafBlock)
         at Markdig.Parsers.MarkdownParser.ProcessInlines(InlineProcessor inlineProcessor, MarkdownDocument document)
         at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline, MarkdownParserContext context)
         at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline, MarkdownParserContext context)
         at BlazorStrap_Docs.Helper.MarkdownToComponent.BuildRenderTree(RenderTreeBuilder builder) in C:\Users\v-zhiyang\Desktop\YOURSELF\BlazorStrap\src\BlazorStrap-Docs\Helper\MarkdownToComponent.cs:line 93
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

.NET Version

9.0.100-preview.7.24375.12

Anything else?

Minimal Repro steps (repro demo attached
MarkdownToHtmlDemo.zip):

1.Create a Blazor Server App project.
2. Install Markdig nuget package.
3. Add a MarkdownToComponent.cs class file with following content:

    public class MarkdownToComponent : ComponentBase
    {
        [Parameter] public RenderFragment? ChildContent { get; set; }
        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {

            string s = @"The following are **guide lines** on howto contribute. You input is always **welcomed** and **appreciated**.

### Feature Request
---
If you feel BlazorStrap is lacking a feature you need or just want please create a issue with the following.
* What does it do
* Why you feel it should exist
* How can it help others";
            string ms = Markdown.ToHtml(s);
        }
    }
  1. Add above component to Counter.razor page.
<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<MarkdownToComponent>Test</MarkdownToComponent>
  1. Build the project.
  2. Update the runtime.config file to run against with dotnet-sdk-dotnet-sdk-9.0.100-preview.7.24375.12.
"frameworks": [
      {
        "name": "Microsoft.NETCore.App",
        "version": "9.0.0-preview.7.24374.12"
      },
      {
        "name": "Microsoft.AspNetCore.App",
        "version": "9.0.0-preview.7.24373.9"
      }
    ],
  1. Launch the project.
  2. Access http://localhost:5000/ from browser.
  3. Navigate to Counter page.
  4. Refresh the Counter page 7 times.

Expected Result:
The Counter page refresh 7 time successfully.

Actual Result:
The Counter page refresh failed at the 7th refresh with following error:

System.InvalidOperationException: 'The parser is in an invalid infinite loop while trying to parse inlines for block [ParagraphBlock] at position ($0, 0, 0-107'

Stack Trace:
   at Markdig.Helpers.ThrowHelper.InvalidOperationException(String message)
   at Markdig.Parsers.InlineProcessor.ProcessInlineLeaf(LeafBlock leafBlock)
   at Markdig.Parsers.MarkdownParser.ProcessInlines(InlineProcessor inlineProcessor, MarkdownDocument document)
   at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline, MarkdownParserContext context)
   at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline, MarkdownParserContext context)
   at MarkdownToHtmlDemo.MarkdownToComponent.BuildRenderTree(RenderTreeBuilder builder) in E:\Demos\MarkdownToHtmlDemo\MarkdownToHtmlDemo\MarkdownToComponent.cs:line 26
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

Findings:

  • 2 apps are all referenced Markdig nuget package and the exception in 2 apps are both thrown from Markdown.ToHtml() method which is used to convert a markdown file sting to html.
  • We tried to reference the Markdig (version 0.37.0) source code instead of install it from nuget package manager, it doesn't repro in debug mode. But if we enable compiler optimizations on debug mode for Markdig project, this issue will repro again. It doesn't have this issue on build#dotnet-sdk-9.0.100-preview.7.24371.4 . We think something changed with optimization code in 9.0.100-preview.7.24375.12 which cause this issue.
  • The Markdig nuget package is used by 5.8k users. It may affect more users in real world.
  • This issue will occurs after switching pages in applications multiple times or refresh the page multiple times. The first time load the page can successful.

@dotnet-actwx-bot @dotnet/compat

@Junjun-zhao
Copy link
Member Author

@mkArtakMSFT Could you help look at this bug and help triage it? In the meantime, could you please help confirm if this is a blocker for .NET 9 Preview 7? Please help move to correct team if it is not correct. Thanks.

@javiercn
Copy link
Member

@Junjun-zhao based on the source of the call stack this doesn't seem blazor specific.

The exception is coming from a third-party component.

   at Markdig.Helpers.ThrowHelper.InvalidOperationException(String message)
   at Markdig.Parsers.InlineProcessor.ProcessInlineLeaf(LeafBlock leafBlock)
   at Markdig.Parsers.MarkdownParser.ProcessInlines(InlineProcessor inlineProcessor, MarkdownDocument document)
   at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline, MarkdownParserContext context)
   at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline, MarkdownParserContext context)

@Junjun-zhao
Copy link
Member Author

Yes @javiercn , the call stack seem come from Markdig nuget package, but this is a behavior change from dotnet-sdk-9.0.100-preview.7.24375.12 as it passed on dotnet-sdk-9.0.100-preview.7.24371.4. Could you please look into what change caused this?

@MackinnonBuck
Copy link
Member

Thanks for reaching out, @Junjun-zhao. In order for us to investigate this further, we need a minimal repro project that doesn't utilize third-party code.

@PriyaPurkayastha
Copy link

@MackinnonBuck we are the .NET AppCompat team and we test 3rd Party apps with latest runtime to log bugs. We try to provide minimal repros wherever possible, but we might not have the expertise to create minimal repro without using 3rd party code. We have provided a repro machine with the two apps that are showing a change in behavior. We would need help from ASPNET Core team to look at the repro machine provided and investigate to root cause the change in behavior - probably review what changes have been made in this space recently that could have introduced the regression.

@Junjun-zhao
Copy link
Member Author

@MackinnonBuck During our further investigation, we found this issue also reproduces with a console app. We tried to reference the Markdig (version 0.37.0) source code instead of installing it from nuget package manager, it doesn't repro in debug mode. But if we enable compiler optimizations on debug mode for Markdig project, this issue will repro. It doesn't reproduce this issue in dotnet-sdk-9.0.100-preview.7.24371.4 build. We think something might do with optimization code in 9.0.100-preview.7.24375.12 which cause this issue and it seems a runtime issue, could you please check and move it to the right team? Thanks.

Update the Minimal repro steps with console project: (repro demo attachedDemoForMarkdownToHtml.zip):
1.Create a Console project.
2. Install Markdig nuget package.
3. Add a following code to Program.cs file:

   using Markdig;

string s = @"The following are **guide lines** on howto contribute. You input is always **welcomed** and **appreciated**.

### Feature Request
---
If you feel BlazorStrap is lacking a feature you need or just want please create a issue with the following.
* What does it do
* Why you feel it should exist
* How can it help others";
for (int i = 0; i < 20000; i++)
{
    string ms = Markdown.ToHtml(s);
}
Console.WriteLine("Hello, World!");
  1. Build the project.
  2. Update the runtime.config file to run against with dotnet-sdk-dotnet-sdk-9.0.100-preview.7.24375.12.
"framework": {
      "name": "Microsoft.NETCore.App",
      "version": "9.0.0-preview.7.24374.12"
    },
  1. Launch the project.

Expected Result:
Console application will output "Hello World!" successful.

Actual Result:
Console application run with following error:

System.InvalidOperationException: 'The parser is in an invalid infinite loop while trying to parse inlines for block [ParagraphBlock] at position ($0, 0, 0-107'

Stack Trace:
   at Markdig.Helpers.ThrowHelper.InvalidOperationException(String message)
   at Markdig.Parsers.InlineProcessor.ProcessInlineLeaf(LeafBlock leafBlock)
   at Markdig.Parsers.MarkdownParser.ProcessInlines(InlineProcessor inlineProcessor, MarkdownDocument document)
   at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline, MarkdownParserContext context)
   at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline, MarkdownParserContext context)
   at MarkdownToHtmlDemo.MarkdownToComponent.BuildRenderTree(RenderTreeBuilder builder) in E:\Demos\MarkdownToHtmlDemo\MarkdownToHtmlDemo\MarkdownToComponent.cs:line 26
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

@javiercn
Copy link
Member

javiercn commented Aug 1, 2024

@Junjun-zhao thanks for the additional details.

This seems to be a regression somewhere in the runtime. I'm transferring the issue

@javiercn javiercn transferred this issue from dotnet/aspnetcore Aug 1, 2024
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Aug 1, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Aug 1, 2024
Copy link
Contributor

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

@Junjun-zhao
Copy link
Member Author

Thanks @jeffschwMSFT for helping check this issue. Could you please help confirm if this is a blocker for .NET 9 Preview7?
There is one another app also affected by this issue and that is 3 apps affected in our lab,

@vcsjones vcsjones removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Aug 2, 2024
@jeffschwMSFT
Copy link
Member

It would need investigation. @jeffhandley could y'all take a look? It looks like a 3rd party nuget break, but perhaps we had a subtle change causing the break.

@jeffhandley jeffhandley added this to the 9.0.0 milestone Aug 6, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Aug 6, 2024
@jeffhandley jeffhandley added the untriaged New issue has not been triaged by the area owner label Aug 6, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Aug 6, 2024
@krwq
Copy link
Member

krwq commented Aug 9, 2024

I was able to pinpoint to #104752 as a source of regression (f455188).

This was done by doing semi-manual (rejecting obviously not culprits and repro requires refreshing the page) binary search between commits 1f70f0c and eedf30e. I had to do it twice because first time I was getting AVs caused by #104336 and then had to do it second time with revert of that commit - the AV is already reverted by #105234 though.

I tried to run original repro after reverting #104752 but I hit non-obvious merge conflict and it's already end of the day for me so will leave it here.

I didn't have much luck narrowing down the repro (other than removing Counter page and putting MarkDownToComponent directly in the Index but that also causes you need to refresh a bit more than 7 times) - it seems to be somewhere between Razor and Markdig - I've tried isolating Markdig piece (i.e. stressed this under multiple threads) but without luck and I'm not familiar with Razor enough to simplify this further quickly.

@krwq krwq added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI and removed area-System.Runtime labels Aug 9, 2024
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@krwq krwq assigned AndyAyersMS and unassigned krwq Aug 9, 2024
@AndyAyersMS AndyAyersMS added the Priority:2 Work that is important, but not critical for the release label Aug 9, 2024
@AndyAyersMS
Copy link
Member

Using the standalone repro the issue is in the codegen for

1652: JIT compiled Markdig.Parsers.InlineProcessor:ProcessInlineLeaf(Markdig.Syntax.LeafBlock):this [Tier1 with Dynamic PGO, IL size=763, code size=6019, hash=0x0f931e6b]

This method has phi-refinements but does not leverage them for copyprop. Will need to dig in to see where things change.

@AndyAyersMS
Copy link
Member

Here's a simple repro case

// DOTNET_TieredCompilation=0
// Should return 100, but returns 99

using System.Runtime.CompilerServices;
class Runtime_105792
{
    [MethodImpl(MethodImplOptions.NoInlining)]
    static int Problem(int x)
    {
        int y = 0;
        while (x != 0)
        {
            if (y == x) return -1;
            y = x;
            Update(ref x);
        }
        return x;
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void Update(ref int x) 
    {
        x = x - 1;
    }

    public static int Main() => 100 + Problem(10);
}

x is not in SSA since it is address exposed.

Phi refinement kicks in for the while loop in Problem, and gives y's back edge phi arg the same value number as x has at the point of the assignment.

This enables RBO to decide that if we come along the loop back edge, we know that x == y, and so we can return -1.

***** BB03 [0001]
STMT00008 ( ??? ... ??? )
N004 (  0,  0) [000023] DA---------                         *  STORE_LCL_VAR int    V01 loc0         d:3 $VN.Void
N003 (  0,  0) [000022] -----------                         \--*  PHI       int    $181
N001 (  0,  0) [000025] ----------- pred BB04                  +--*  PHI_ARG   int    V01 loc0         u:4 <l:$182, c:$83>
N002 (  0,  0) [000024] ----------- pred BB02                  \--*  PHI_ARG   int    V01 loc0         u:2 $42

***** BB03 [0001]
STMT00002 ( 0x004[E-] ... 0x006 )
N004 (  7,  6) [000009] ----G------                         *  JTRUE     void   $VN.Void
N003 (  5,  4) [000008] N---G--N-U-                         \--*  NE        int    <l:$1c3, c:$1c4>
N001 (  1,  1) [000006] -----------                            +--*  LCL_VAR   int    V01 loc0         u:3 (last use) $181
N002 (  3,  2) [000007] ----G------                            \--*  LCL_VAR   int   (AX) V00 arg0          <l:$182, c:$82>

Not sure how to fix this. Seems like we might need to do something similar to hoisting here, where we realize that a VN is loop dependent?

@dotnet/jit-contrib any thoughts?

@jakobbotsch
Copy link
Member

Not sure how to fix this. Seems like we might need to do something similar to hoisting here, where we realize that a VN is loop dependent?

@dotnet/jit-contrib any thoughts?

Hmm yeah, I agree, I think the refinement can only be done with VNs that we can prove to be invariant in the loop we are refining for. Otherwise the same VN can take on different values, as in this example.

AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this issue Aug 10, 2024
PhiArg VNs should be invariant in the loop that contains the Phi, otherwise
the same VN may refer to values from more than one iteration.

Fixes dotnet#105792.
@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Aug 10, 2024
@Junjun-zhao
Copy link
Member Author

Verified this issue with dotnet-sdk-9.0.100-rc.1.24417.9, it has been fixed.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 19, 2024
mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this issue Dec 10, 2024
PhiArg VNs should be invariant in the loop that contains the Phi, otherwise
the same VN may refer to values from more than one iteration.

Fixes dotnet#105792.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI blocking-release in-pr There is an active PR which will close this issue when it is merged Priority:2 Work that is important, but not critical for the release regression-from-last-release
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants