Skip to content

Cyclic values crash recursive Value traversals (Display, Ord, Eq, Hash) #200

Description

@timfennis

Repro

let x = [];
x.push(x);
print(x);          // stack overflow, process aborts

Any Value traversal that recurses structurally has no cycle handling, so a value that (transitively) contains itself crashes the interpreter with a stack overflow or a nested RefCell borrow panic. print is the obvious entry point, but the same applies to:

  • Displayprint, string interpolation, and any error message that formats a value. Found via feat(stdlib): make json_encode strict and add json_encode_lossy 🧊 #199: json_encode_lossy on a map with a cyclic non-string key crashes inside key.to_string(), and even strict json_encode's rejection message (cannot convert a map with non-string key {key}) crashes while formatting the key.
  • Ord/PartialOrd — comparing two cyclic lists recurses forever (also reachable through heap operations, sort, etc.).
  • Eq/Hash — equality checks and using a cyclic value as a map key.

The big-stack thread from #176 doesn't help here: cycles are infinite, not merely deep.

Scope

#199 added cycle detection to the JSON encoder's own traversal (visited-pointer set on the recursion path), but it can only protect paths it owns — as soon as it calls Display for key stringification it inherits the crash. The fix belongs in the trait impls in ndc_vm, not in per-caller workarounds.

Possible direction

Track visited Rc pointers during Display and print a placeholder for back-references, the way Python prints [1, [...]]. Ord/Eq/Hash need their own decision (a placeholder isn't meaningful there — erroring or defining cycles as equal-by-identity are options). Alternatively, decide whether cyclic values should be constructible at all.

🤖

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions