Skip to content

fix(corekit): raise ProtocolError for a NumberField negative bit_length (#831) - #834

Merged
JarryShaw merged 1 commit into
mainfrom
fix/831-numberfield-bitlength-shift
Sep 26, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/831-numberfield-bitlength-shift

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

Closes #831

What is the purpose of your pull request?

  • fix — corrects a defect

Description

#829 guarded the eager 1 << length shift in NumberField.__call__; the
sibling shift in __init__ — (1 << bit_length) - 1 — was still open, so
NumberField(length=4, bit_length=-1) raised a bare ValueError instead
of a catchable ProtocolError.

Also closes the second half: __call__'s negative-length guard used to
sit only inside the bit_length-not-supplied branch, so a field with a
fixed bit_length and a callable length resolving negative produced a
different ProtocolError message (template='...-1s', from
FieldBase.length) than one with no bit_length at all
(length=...). The guard now runs unconditionally, so both raise the
same message. No in-tree call site combines the two (verified against
vlan.py's three bit_length fields, which all take positive literals).

New tests in tests/corekit/test_fields_numbers_negative_length.py
(NegativeBitLengthTests), shown failing on stock 5576708d4 before the
fix. coverage run on tests/corekit/ + tests/protocols/application/:
numbers.py stays at 100% (142→144 stmts). The pinned negative-length
assertion in test_http_unit.py is untouched.

…th (#831)

`NumberField.__init__` shifted by `bit_length` eagerly --
`(1 << bit_length) - 1` -- so a negative `bit_length` raised a bare,
uncatchable `ValueError` instead of a pcapkit error. #829 guarded the
sibling shift in `__call__` (a negative resolved `length`) but left this
one, at numbers.py:88, open.

- `__init__` now raises `ProtocolError` for a negative `bit_length`,
  naming `bit_length=` rather than a resolved byte length, since that is
  what is wrong.
- `__call__`'s existing negative-`length` guard now runs unconditionally
  instead of only inside the `bit_length`-not-supplied branch, so a field
  combining a fixed `bit_length` with a callable `length` that resolves
  negative raises the same message as one with no `bit_length` at all,
  instead of a different one from `FieldBase.length` later.

`coverage run -m pytest` on tests/corekit/ and tests/protocols/application/:
numbers.py stays at 100% (142->144 stmts, 0 missed both). The pinned
negative-length assertion in test_http_unit.py is untouched.
@JarryShaw JarryShaw added bug Issues reporting a defect (set by the bug report template; a default, not an assessment) fix Pull requests that fix a defect (fix: subject prefix) test Pull requests that add or correct tests (test: subject prefix) review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 26, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO — cross-review (opus, independent tree, pcapkit.__file__ printed per run) confirms all six load-bearing claims.

One correction, which I re-derived myself: the description undersells the delta. It is not only "a leaked ValueError becomes a ProtocolError". On 3118ed796 a field with bit_length set and a negative-resolving callable length was usable for building:

stock, fresh field:  .length         -> ProtocolError "…template='>-1s'"
stock, same field:   .pack(0xff, {}) -> b'\xff'   and silently sets _length = 1
stock, then:         .length         -> 1          (the incoherence heals itself invisibly)
PR:                  construct+call  -> ProtocolError "…length=-1"

So a pack() that returned bytes now raises. Still the right change: the stock state was self-contradictory, the width pre_process derived came from the value rather than the declared length, and #829 already drew this line for the bit_length-omitted case — this makes the two branches agree.

Unreachable in-tree: the only bit_length= sites are vlan.py:47,49,51, all positive literals.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 26, 2026
@JarryShaw
JarryShaw merged commit d0f44b4 into main Sep 26, 2026
31 checks passed
@JarryShaw
JarryShaw deleted the fix/831-numberfield-bitlength-shift branch September 26, 2026 12:15
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Sep 26, 2026
@JarryShaw JarryShaw added this to the 1.5 milestone Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Issues reporting a defect (set by the bug report template; a default, not an assessment) fix Pull requests that fix a defect (fix: subject prefix) test Pull requests that add or correct tests (test: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(fields): NumberField.__init__'s bit_mask shift still leaks a bare ValueError, and #829's guard is skipped when bit_length is supplied

1 participant