Skip to content

fix(httpv2): SETTINGS ListField reads past the last pair and warns 'packet length < 0' - #1146

Merged
JarryShaw merged 1 commit into
mainfrom
fix/1140-settings-listfield
Oct 6, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/1140-settings-listfield

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner
  • Searched for similar pull requests
  • Followed the coding style (make pylint, make mypy, make isort) — isort clean, mypy 0 errors in the touched file; pylint not run with project flags
  • make test passes, and a test case covers the change — the modules listed below only
  • Added a changelog entry — N/A, added centrally after the wave

What is the purpose of your pull request?

  • fix — corrects a defect
  • feat — adds a feature
  • perf — changes performance, not behaviour
  • refactor — changes neither behaviour nor performance
  • test — tests only
  • docs — documentation only
  • ci — workflows or build tooling
  • release — bumps the version or rolls up a distribution
  • chore — anything else

Description of your pull request and other information

Closes #1140. SettingsFrame.settings built each SettingPair as a SchemaField with no length, so the nested schema began at __length__ = -1 and warned at -3 and -7 for every pair. The ListField loop itself stops correctly. The fix gives the item its fixed 6-octet size, as TCP SACK (length=8) and SCTP gap-ack (length=4) already do.

Probe (1 pair, 0x0001 = 4096): before, ['packet length < 0: -3', 'packet length < 0: -7']. After, []. Malformed 5, 7 and 9-octet payloads still raise ProtocolError, now without the warnings.

Test. The new tests/protocols/application/test_httpv2_settings_list_1140_unit.py covers 0, 1, 2 and 6 pairs plus an ACK, with frames packed by scapy 2.7.0 contrib.http2. It asserts zero warnings and a byte-for-byte parse→make round trip. Without the fix: 3 failed, 2 passed, 7 subtests passed (1, 2 and 6 pairs). With it: 2 passed, 10 subtests passed.

Also passing: test_httpv2_frame_length_1121_unit (5), test_httpv2_negative_length_unit (5), test_httpv2_payload_length_unit (23), test_http_unit (65), test_option_roundtrip_unit (6), test_enum_lookup_reparent_877_unit (37) and tests/project (385 passed, 1 skipped).

…acket length < 0'

SettingsFrame.settings built each SettingPair as a SchemaField with no
length, so the nested schema started from a __length__ of -1 and warned
'packet length < 0' at -3 and -7 for every pair. Give the item its fixed
6-octet size, as TCP SACK and SCTP gap-ack blocks already do.

Closes #1140
@JarryShaw JarryShaw added fix Pull requests that fix a defect (fix: subject prefix) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 6, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review verdict on 30f45c86c: GOOD TO GO (ran on Sonnet; author Opus)

  • Root cause confirmed: a SchemaField with no length passes -1 as the remaining length (misc.py:746), so the two subfields of SettingPair drive it to −3 and then −7. ListField itself stops at the correct point.
  • Warnings: with warnings promoted to errors, frames with 1, 2 and 6 pairs (including extreme values) raise on main and pass on this PR. A frame with 0 pairs and an ACK pass on both.
  • Round-trip: all six frames re-pack to scapy's exact bytes, and scapy re-parses pcapkit's output to the same bytes.
  • Malformed payloads: 1, 5, 7, 9, 11 and 13 octets still raise ProtocolError, now without warnings.
  • length=6: matches RFC 9113 §6.5.1 (16-bit identifier plus 32-bit value). This is the only length-less SchemaField in the file.
  • Tests: with the fix reverted, the new module fails 3 tests.

The same length-less pattern also appears in mh and hip; that is tracked in #1148.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Coverage: 88.75% (unit tier, Python 3.14, 30f45c86c, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 4 93.55%
pcapkit/const 18757 1035 2342 846 90.23%
pcapkit/corekit 1873 91 578 22 94.33%
pcapkit/dumpkit 136 0 40 0 100.00%
pcapkit/foundation 2425 145 842 34 92.56%
pcapkit/interface 112 7 40 5 92.11%
pcapkit/protocols 15659 188 3944 163 98.18%
pcapkit/toolkit 487 65 144 1 85.42%
pcapkit/utilities 429 4 122 4 98.55%
pcapkit/vendor 4409 2359 1006 158 42.84%

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

@JarryShaw
JarryShaw merged commit 4a43043 into main Oct 6, 2026
41 checks passed
@JarryShaw
JarryShaw deleted the fix/1140-settings-listfield branch October 6, 2026 22:36
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 6, 2026
@JarryShaw JarryShaw added this to the PyPCAPKit v1.5 milestone Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Pull requests that fix a defect (fix: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(httpv2): SETTINGS ListField reads past the last pair and warns 'packet length < 0'

1 participant