Skip to content

loadNewBlocks only detects direct self-loops — multi-block circular connections can trigger recursive stack overflow during project load #7391

@sahu-virendra-1908

Description

@sahu-virendra-1908

Description

While reviewing the block-loading pipeline in Music Blocks, I noticed that the circular connection validation inside:

js/blocks.js

only checks for direct self-references (A → A) and does not detect larger cyclic graphs such as:

A → B → A

or:

A → B → C → A

Current validation logic:

for (const c in blkData[4]) {
    if (blkData[4][c] === blkData[0]) {
        console.debug("Circular connection in block data: " + blkData);
        return;
    }
}

This prevents only direct self-loops.

However, multi-block cycles are still accepted and later processed by recursive traversal functions such as:

  • _calculateDragGroup
  • adjustDocks

Both functions contain loop counters (dragLoopCounter, _loopCounter), but these counters only limit iteration count after recursion has already expanded the JavaScript call stack.

For sufficiently deep cyclic or chained graphs, recursion can still grow large enough to trigger:

RangeError: Maximum call stack size exceeded

during project loading or block traversal.

Expected Behavior

Project loading should reject all cyclic block graphs before recursive traversal begins.

Malformed or corrupted project files containing circular connections should fail gracefully instead of triggering recursive traversal loops.

Recursive graph traversal should also avoid unbounded recursive stack growth for large block graphs.

Current Behavior

Only direct self-loops are rejected.

More complex cyclic graphs can still pass validation and later cause recursive traversal between connected blocks.

Example:

0 → 1 → 0

or:

0 → 1 → 2 → 0

These cycles can repeatedly recurse through:

  • _calculateDragGroup
  • adjustDocks

eventually overflowing the JavaScript call stack for sufficiently large graphs.

Steps to Reproduce

  1. Open Music Blocks
  2. Open DevTools Console
  3. Run:
const maliciousProject = [
    [0, "start", 100, 100, [null, 1, null]],
    [1, "action", 200, 100, [0, null, null]]
];

activity.blocks.loadNewBlocks(maliciousProject);
  1. Observe recursive traversal repeatedly revisiting connected blocks
  2. Larger cyclic graphs can eventually trigger:
RangeError: Maximum call stack size exceeded

Root Cause

The current validation logic only checks whether a block directly references itself.

It does not validate the overall connection graph for indirect cycles.

Later recursive traversal functions assume the graph is acyclic and recursively walk connections without robust cycle protection.

Suggested Fix

Fix 1 — Detect full graph cycles during project load

Instead of checking only direct self-loops, build a connection graph and run proper DFS/BFS cycle detection before blocks are loaded.

Example approach:

  • build adjacency map
  • track visited nodes
  • detect back edges/cycles
  • reject cyclic project graphs before traversal begins

Fix 2 — Replace recursive traversal with iterative traversal

Functions such as:

  • _calculateDragGroup
  • adjustDocks

could be converted to iterative traversal using:

  • queue
  • stack
  • visited set

This prevents deep recursive call chains and avoids stack overflow even for very large block graphs.

Why This Matters

Malformed or corrupted project files can currently create recursive traversal loops during project loading.

This may lead to:

  • browser freezes
  • stack overflow errors
  • incomplete project loads
  • unstable editor state
  • crashes for very large cyclic block graphs

Checklist

  • I have read and followed the project's code of conduct.
  • I have searched for similar issues before creating this one.
  • I have provided all the necessary information to understand and reproduce the issue.
  • I am willing to contribute to the resolution of this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions