Skip to content

Excessive Recursion in modelFromJSON Causes Stack Overflow ( Parser Depth Handling Bug ) #8632

@amadhan882

Description

@amadhan882

Excessive Recursion in modelFromJSON Causes Stack Overflow ( Parser Depth Handling Bug )


System information

  • Have I written custom code: Yes (minimal PoC)
  • OS Platform: Windows 11
  • Mobile device: N/A
  • TensorFlow.js installed from: npm
  • TensorFlow.js version: @tensorflow/tfjs@4.22.0
  • Browser version: N/A (Node.js execution)
  • TensorFlow.js Converter Version: Not applicable
  • Node.js runtime: v22.18.0

Describe the current behavior

When calling:

tf.models.modelFromJSON(...)

with a model configuration containing extremely deep nested "config" objects, the parser crashes with:

RangeError: Maximum call stack size exceeded

The model loader recursively walks through the configuration without:

  • enforcing a maximum nesting depth
  • validating input structure
  • switching to an iterative-safe traversal

This results in a JavaScript stack overflow during JSON model parsing.

This is a robustness bug affecting model loading of malformed or accidentally nested config structures.


Describe the expected behavior

The parser should gracefully reject unreasonably deep configurations.

Expected safeguards:

  • Detect excessive nesting (e.g., > 1000 levels)
  • Abort with a clear error message such as:
    “Model configuration depth exceeds supported limit.”
  • Avoid triggering recursive stack overflow.

This improves resilience when handling corrupted, user-generated, or automated model configs.


Standalone code to reproduce the issue

Save as reproduce_tfjs_parser_depth_bug.js:

const tf = require('@tensorflow/tfjs');

async function checkParserStability() {
    console.log("[*] Testing Parser Depth Limits...");

    const depth = 5000;   // large enough to exceed JS call stack
    let nestedConfig = { layers: [] };
    let current = nestedConfig;

    // Generate deeply nested `"config"` chain
    for (let i = 0; i < depth; i++) {
        current.config = { layers: [] };
        current = current.config;
    }

    const modelStructure = {
        "modelTopology": {
            "class_name": "Sequential",
            "config": nestedConfig
        }
    };

    try {
        await tf.models.modelFromJSON(modelStructure);
    } catch (err) {
        console.log("Status:", err.message);
    }
}

checkParserStability();

How to run

node reproduce_tfjs_parser_depth_bug.js

Observed output

[*] Testing Parser Depth Limits...
Status: Maximum call stack size exceeded

Depth values >2000–3000 consistently trigger the same failure.


Explanation

The underlying issue is unbounded recursive descent in the model loader's configuration parsing.

Because JavaScript engines (V8 on Node.js) impose strict call-stack limits, this leads to:

  • Call stack exhaustion
  • Immediate crash inside modelFromJSON
  • No graceful recovery path

While not a security issue, this is a correctness and stability bug for any workflow that processes:

  • Auto-generated configs
  • Third-party model JSON
  • Machine-generated nested structures
  • Corrupted or malformed models

Adding a depth-checking guard or iterative parsing would prevent this runtime crash.


Other info / logs

  • Not browser-specific (reproduces in Node.js)
  • No native memory access; pure JS error

Conclusion

The modelFromJSON parser lacks a recursion depth limit, making the library vulnerable to uncontrolled recursion (CWE-674).
This allows malformed or deeply nested configurations to exhaust the JavaScript call stack, causing an immediate process crash.

To ensure reliability and prevent runtime termination, the parser should:

  • Implement a maximum nesting depth guard, or
  • Use an iterative traversal strategy instead of deep recursion.

Adding these safeguards would prevent call-stack crashes and improve TensorFlow.js robustness when handling complex or malformed inputs.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions