Skip to content

fix(protocols): record a cut option area or SCTP padding where the data ends (#2680) - #2682

Merged
JarryShaw merged 1 commit into
mainfrom
fix/2680-sctp-schema-padding
Nov 3, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/2680-sctp-schema-padding

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • fix — corrects a defect

Description of your pull request and other information

SCTP's capture cuts now go through Schema's built-in short read, with no per-protocol override.

Cut sweeps over every padding offset (bytes, streams, IPv4 and IPv6), standalone chunk schemas, and a TCP option area cut at every offset all fail on main. Every leg passes, apart from the CI-script failures main also has. Shipped captures are identical to main.

Closes #2680
Closes #2685

@JarryShaw JarryShaw added this to the PyPCAPKit v1.6 milestone Nov 2, 2026
@JarryShaw JarryShaw added bug Issues reporting a defect (set by the bug report template; a default, not an assessment) review: running A cross-review is in flight against the current head - no verdict yet labels Nov 2, 2026
@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: running A cross-review is in flight against the current head - no verdict yet labels Nov 2, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES: wrong layer. Schema.unpack already records a field cut by the end of the data (_note_short_read), and pack() cuts back to the octets read (_cut_short_read). That covers PaddingField too. The record never fires for SCTP because the schema module's padding_length caps the padding at the octets left, so a cut padding reads as complete; on pack, the length is recomputed at full width. On main, DATAChunk.unpack on 22 octets packs 24 with no record.

The rework removes the cap so the built-in records the cut, which also fixes a chunk schema on its own. It drops this PR's separate padding check in the SCTP.unpack override, and it audits other padding helpers that cap the same way.

@JarryShaw JarryShaw moved this to In review in PyPCAPKit Nov 2, 2026
@JarryShaw
JarryShaw force-pushed the fix/2680-sctp-schema-padding branch from 4c4b0a3 to c4e9af7 Compare November 2, 2026 23:24
@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Nov 2, 2026
@JarryShaw JarryShaw changed the title fix(transport): pack an SCTP schema cut inside its last padding as captured (#2680) fix(protocols): record a cut option area or SCTP padding where the data ends (#2680) Nov 2, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed the rework, 4c4b0a324→c4e9af739. This PR now closes #2680 and #2685. SCTP capture cuts go through Schema's built-in short read:

A Sonnet re-review is running.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: running A cross-review is in flight against the current head - no verdict yet labels Nov 3, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES at c4e9af739 (tests only), from a Sonnet re-review. The fix is correct, and the review found no regression:

  • 1696 SCTP cut rows rebuild exactly; 56 fail on main.
  • A TCP option-area cut rebuilds exactly.
  • In a 903,528-row schema sweep across nine protocols, 7,222 rows go from inexact to exact and none get worse.
  • The merged tree passes 198 modules.

The scoped hook is the right shape: it declares a policy and leaves recording to the built-in. Its scoping is not pinned, though:

  1. If PaddedOptionField accepts any short read, every test still passes, so an SCTP parameter or cause whose Length runs past its chunk would no longer be refused. Pin that refusal (runs past the end of the data).
  2. Pin the record on TCP cuts at 20–22 octets, which land before the EOOL is consumed, so dropping the hand-back note fails the new modules and not only fix(transport): an SCTP packet cut short by the capture does not rebuild as captured #2673's.
  3. If you can, kill the surviving min() (kept = consumed), no-hand-back-note and max(area, 0) mutants.

…ta ends (#2680)

Schema.unpack gave back a cut OptionField area's remainder by its declared
width, keeping and rewinding octets never read, and charged the cut to the
field before it parsed; #2679's SCTP.unpack override worked round that for
SCTP alone and could not read a stream that does not seek. padding_length
capped SCTP padding at the octets left, so a chunk cut inside it packed at
full width: 34 octets in, 36 out.

- Schema.unpack gives back no more of the remainder than it read, and charges
  the cut to the option field only when none is given back.
- ChunkListField reports its remainder in declared terms; the override is gone.
- padding_length returns the padding the Length calls for. OptionField.unpack
  asks _accepts_short_read before refusing a short option (#1325), and
  refuses by default, since a general padding rule accepts the PadN overruns
  #1325 refuses; PaddedOptionField accepts SCTP's, which the Length leaves out.
- Tests: SCTP items cut at every padding offset, alone, nested and bundled, on
  bytes, streams and envelopes; a TCP option area cut at every offset; SCTP on
  a stream that cannot seek; an SCTP item overrunning its chunk, still refused;
  an option reporting more than it read. #2679's tests pass unchanged.

Every unittest leg passes; captures parse identically to main.

Closes #2680
Closes #2685
@JarryShaw
JarryShaw force-pushed the fix/2680-sctp-schema-padding branch from c4e9af7 to acf8920 Compare November 3, 2026 00:40
@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Nov 3, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO at acf8920a4, rebased onto 57a6c366d. This round changed tests only: pcapkit/'s patch-id matches the reviewed c4e9af739. The re-review's gaps are closed:

  • Hook scoping is pinned: an SCTP parameter or cause whose Length runs past its chunk is still refused.
  • The hand-back record is pinned by TCP cuts at 20–23 octets.
  • The surviving mutants are now killed: the min() and no-note branches, by an over-reporting test option.
  • max(area, 0) stays as it is: that mutant is equivalent, since the only ChunkListField sizes its area with max(..., 0) already.

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Coverage: 94.42% (unit tier, Python 3.15, acf8920a4, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 21062 177 2914 158 98.56%
pcapkit/corekit 2794 74 890 37 96.77%
pcapkit/dumpkit 281 3 100 3 98.43%
pcapkit/foundation 3507 27 1218 32 98.75%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 22637 154 5928 138 98.96%
pcapkit/toolkit 961 26 342 8 96.62%
pcapkit/utilities 513 7 144 5 98.17%
pcapkit/vendor 5590 2286 1280 214 55.75%

Per-file detail: the coverage-html artifact of this run.

@JarryShaw
JarryShaw merged commit bd82b76 into main Nov 3, 2026
97 checks passed
@JarryShaw
JarryShaw deleted the fix/2680-sctp-schema-padding branch November 3, 2026 02:12
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Nov 3, 2026
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Nov 3, 2026
JarryShaw added a commit that referenced this pull request Nov 3, 2026
… helpers, MH options 6 and 27, the cut SCTP and option-area schemas and dict-built secrets into 1.6.0 (#2449)

- Breaking: a make() enumeration field takes a member or an int, its
  X_default/X_namespace/X_reversed keywords removed with no alias, and names,
  wide codes and wide option codes are refused (#2692); the schema helpers
  move to pcapkit.corekit.schema and pcapkit.corekit.fields.byteorder is
  removed (#2704); MobileNetworkPrefixOption gains prefix_length and keeps an
  IPv6Address prefix, and TimestampOption's timestamp is None past 9999
  (#2709). Folded into the MH data-model entry; old values measured against
  v1.5.1.
- Fixed: the SCTP schema cut inside its padding and a header schema cut
  inside an option area pack back as captured (#2682), into the SCTP entry;
  a Decryption Secrets Block rebuilds from its dict as captured (#2707), into
  the DSB entry.
- Folded into unreleased entries: FRAD's Q.922 address refusal and quiet cut
  rebuild (#2719); a from_data rebuild's checksum status (#2712); a failed
  ListField fill's ledger (#2706); pad_length's path (#2704); TLS's enumeration
  fields (#2692); the make() and schema-helper rulings, into the conventions
  entry (#2692, #2704); the GraalPy shards, into the CI-legs entry (#2720).
- 1.5.0's corekit.fields.byteorder role points at corekit.schema.byteorder,
  where #2704 moved it, so the nitpicky build does not warn on it; 1.5.0's
  text unchanged.
- No entry for the test-only 72b2bd8 (#2715), or the docs-and-test-only
  0c07940 (#2718).
- CHANGELOG.md regenerated; util/changelog_md.py --check passes.
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)

Projects

Status: Done

1 participant