Skip to content

expression: weak-reference the singleton intern table to bound memory - #1530

Merged
serpilliere merged 1 commit into
cea-sec:masterfrom
mrexodia:weakref
Aug 10, 2026
Merged

expression: weak-reference the singleton intern table to bound memory#1530
serpilliere merged 1 commit into
cea-sec:masterfrom
mrexodia:weakref

Conversation

@mrexodia

@mrexodia mrexodia commented May 31, 2026

Copy link
Copy Markdown
Contributor

Claude found this when my deobfuscation script was growing to 50+GB memory usage, works really well!

Expr.args2expr (the singleton intern cache) held a STRONG reference to every
expression ever created, so it grew without bound on long analyses (symbolic
execution of obfuscated code created millions of transient expressions that were
never freed -> tens of GB, swapping).

Make Expr instances weak-referenceable (add __weakref__ to Expr.__slots__) and
change args2expr / canon_exprs to weakref.WeakValueDictionary / WeakSet, so
transient expressions are garbage-collected once unreferenced while live ones
(still held elsewhere) stay interned -- singleton identity and value equality are
preserved. Subclasses now declare only their own slots (base slots, incl.
__weakref__, are inherited; the previous `Expr.__slots__ + [...]` redeclared base
slots, which both wasted memory and is disallowed for __weakref__).

Measured: a long symbolic-execution analysis dropped from ~13GB (and climbing) to
~155MB peak with no change in results.
@serpilliere
serpilliere merged commit 45fb836 into cea-sec:master Aug 10, 2026
2 checks passed
@serpilliere

Copy link
Copy Markdown
Contributor

Hey @mrexodia !
I don't see any downsides here so let's merge this

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.

2 participants