Skip to content

EnumSchema registries retain every looked-up code, so a lookup miss leaks and contaminates later parses #555

Description

@JarryShaw

An EnumSchema registry gains a permanent entry for any code you merely look up, whether or not that code is registered. Measured on main at e7e9ba98f, repo venv, pcapkit.__file__ asserted to the tree:

>>> probe = OptionNumber(156)
>>> probe in Option.registry
False
>>> _ = Option.registry[probe]          # one bare subscript
>>> probe in Option.registry
True

156 is unassigned, nothing registered it, and a single read created it.

Why this matters twice over

Unbounded growth. Every unrecognised code encountered while parsing is retained for the process lifetime. A capture full of junk option codes grows the registry without limit.

Cross-capture contamination. The registry is class-level, so entries created while parsing one file are visible to the next. Two parses of different files in one process do not start from the same state, which makes behaviour order-dependent and bug reports hard to reproduce.

This is a known defect at the wrong layer

Exactly this bug was fixed at the protocol layer by #425 and #428, for __proto__ dispatch registries. #428's own review acknowledged the schema layer needed the same treatment, in its words "a follow-up issue, split the same way #425 was" — and that issue was never filed. Found by a sweep of deferred work across this release's 68 merged PRs.

So the fix is likely to be the same shape as #425/#428's, and those are worth reading first rather than designing afresh.

A caution on the fix

EnumSchema.registry returning a default for a miss is presumably deliberate — it is how an unknown option falls back to UnassignedOption. The defect is the retention, not the fallback. So the fix should keep returning the default while not writing it, which is a narrower change than replacing the lookup.

Coverage

A test asserting that a lookup miss leaves len(registry) unchanged, and separately that the miss still returns the expected default. Prove both fail without the fix, with the exit code read from a file.

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

    bugIssues reporting a defect (set by the bug report template; a default, not an assessment)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions