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

[Class Diagrams] Multiple comma-delimited generic types results in infinite recursion #4555

Closed
jakraft opened this issue Jun 28, 2023 · 1 comment · Fixed by #4534
Closed
Labels
Status: Triage Needs to be verified, categorized, etc Type: Bug / Error Something isn't working or is incorrect

Comments

@jakraft
Copy link

jakraft commented Jun 28, 2023

Description

Attempting to use the generic type syntax with multiple comma-delimited types results in infinite recursion. Here are some examples of class diagrams that will cause this error:

```mermaid
classDiagram
  class Foo {
    +FunctionA(Dictionary~string, int~)
    +FunctionB() Dictionary~string, int~
    +FunctionC(List~Dictionary~string, int~~)
  }
```

The error produced in the console is:

view fail RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at parseGenericTypes (state.0d8f293e.js:9:30678)
    at parseGenericTypes (state.0d8f293e.js:9:30729)
    at parseGenericTypes (state.0d8f293e.js:9:30729)
    at parseGenericTypes (state.0d8f293e.js:9:30729)
    ...

Steps to reproduce

  1. Go to the live code editor from any browser and open developer tools
  2. Paste the code sample into the live editor
  3. The diagram will fail to render, and console logs will show the error above

Screenshots

No response

Code Sample

classDiagram
  class Foo {
    +FunctionA(Dictionary~string, int~)
    +FunctionB() Dictionary~string, int~
    +FunctionC(List~Dictionary~string, int~~)
  }

Setup

  • Mermaid version: 10.2.3
  • Browser and Version: Edge

Suggested Solutions

The error is in this function:

export const parseGenericTypes = function (text: string): string {
let cleanedText = text;
if (text.split('~').length - 1 >= 2) {
let newCleanedText = cleanedText;
// use a do...while loop instead of replaceAll to detect recursion
// e.g. Array~Array~T~~
do {
cleanedText = newCleanedText;
newCleanedText = cleanedText.replace(/~([^\s,:;]+)~/, '<$1>');
} while (newCleanedText != cleanedText);
return parseGenericTypes(newCleanedText);
} else {
return cleanedText;
}
};

There are multiple issues with this function.

  1. The regex does not account for commas or spaces in between the tildes, so it enters the if-statement on line 183 but fails to replace the tildes with angle brackets.
  2. Since the regex replace fails in step 1, the method exits the do-while loop and immediately calls parseGenericTypes again with the same string (hence the infinite recursion).

The solution for the infinite recursion would be to remove the recursive call on line 193, since that shouldn't be needed at all. However, that still would not address the issue of supporting comma-separated generic types as the output would still include tildes in the render.

The best solution by far would be to simply remove the tilde syntax altogether and add support for angle brackets instead:

export const parseGenericTypes = function (text: string): string {
  let cleanedText = text.replace("<", "&lt;");
  return cleanedText.replace(">", "&gt;");
};

Although this would be a breaking change, it would eliminate all possible ambiguities when pairing up the opening and closing braces.

Additional Context

No response

@jakraft jakraft added Status: Triage Needs to be verified, categorized, etc Type: Bug / Error Something isn't working or is incorrect labels Jun 28, 2023
@jgreywolf jgreywolf linked a pull request Jun 29, 2023 that will close this issue
4 tasks
@jgreywolf
Copy link
Contributor

I believe this should be handled with PR #4534

Also, closing as duplicate of #4431

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Triage Needs to be verified, categorized, etc Type: Bug / Error Something isn't working or is incorrect
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants