Skip to content

Conversation

@dguido
Copy link
Member

@dguido dguido commented Jan 22, 2026

Summary

  • Fix RecursionError when analyzing cyclic pickle structures (e.g., L = []; L.append(L))
  • Detect cycles at mutation points (Append, Appends, SetItem, SetItems, AddItems) and replace self-references with <cyclic-ref> placeholder AST nodes
  • Add has_cycles property to Pickled class for downstream awareness

Fixes #196

Test plan

  • test_cyclic_pickle_dos passes (previously marked as expected failure)
  • test_cyclic_pickle_creates_placeholder verifies placeholder is created
  • All 87 existing tests pass
  • Linter checks pass

🤖 Generated with Claude Code

dguido and others added 3 commits January 22, 2026 01:17
Adds new subcommands to expose PyTorchModelWrapper and polyglot module
functionality via the CLI while maintaining full backward compatibility.

New commands:
- fickling pytorch identify FILE      - Detect PyTorch format(s)
- fickling pytorch show FILE          - Decompile internal pickle
- fickling pytorch check-safety FILE  - Safety check internal pickle
- fickling pytorch inject FILE ...    - Inject payload into model

- fickling polyglot identify FILE     - Identify all possible formats
- fickling polyglot properties FILE   - File property analysis
- fickling polyglot create F1 F2 -o O - Create polyglot file

All commands support --json output and gracefully handle missing torch
dependency with helpful installation instructions.

Closes #101

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace nested subcommands (pytorch/polyglot) with flat, auto-detecting commands:
- fickling check FILE: Safety check any pickle/model (auto-detects format)
- fickling inject FILE -c CODE -o OUT: Inject payload into any format
- fickling info FILE: Show format and properties
- fickling create-polyglot F1 F2 -o OUT: Create polyglot files

Key changes:
- Add auto_load() to loader.py for automatic format detection
- Rewrite cli.py with flat command structure
- Delete cli_pytorch.py and cli_polyglot.py (absorbed into cli.py)
- Maintain full backward compatibility with legacy flags
- Update tests for new interface

The tool now figures out if input is PyTorch, TorchScript, plain pickle, etc.
without users needing to specify format explicitly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cyclic pickle structures (e.g., `L = []; L.append(L)`) caused
RecursionError when fickling analyzed them. This fix detects cycles
at mutation points (Append, Appends, SetItem, SetItems, AddItems)
and replaces self-references with `<cyclic-ref>` placeholder AST nodes.

Changes:
- Add `_has_cycle` flag to Interpreter to track cycle detection
- Modify mutation operations to check if value being added `is` the container
- Add `has_cycles` property to Pickled class for downstream awareness
- Update tests to verify the fix works correctly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@dguido dguido requested a review from ESultanik as a code owner January 22, 2026 08:18
dguido added a commit that referenced this pull request Jan 22, 2026
The cyclic AST recursion issue (#196) is being fixed separately in PR #213.
Mark this test as expected failure so PR #211 CI can pass.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This was erroneously added and later removed in PR #210. The visitor
override tracks visited nodes by id to prevent infinite recursion when
traversing cyclic AST structures created via MEMOIZE + GET opcodes.

Co-Authored-By: Dan Guido <dan@trailofbits.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Denial of Service via Infinite Recursion on Cyclic Pickles

3 participants