…top draining HTTP's explicit version= buffer
* ipv6_route.py's three `_read_data_type_*` diagnostics interpolated a bare
`{type}`, which resolves to the builtin `type` since none of the enclosing
methods bind a `type` parameter, so every message read
`[TypeNo <class 'type'>]` instead of the routing type number. `header.type`
is already in scope with the value wanted, so no signature change is
needed. Also normalises `_read_data_type_src`'s punctuation to the
colon-before-bracket form the other two sites and `mh.py`'s `_make_opt_*`
family already use.
* http.py's `HTTP.read`'s explicit `version=` path passed `self._file` --
already drained by the outer read -- to the sub-protocol constructor,
instead of `self._data` as `_guess_version` does, so it built the
sub-protocol from a short or empty buffer. Passes `self._data` on both
paths, and wraps a malformed payload's bare `ValueError` escaping that path
in a chained `ProtocolError`, matching `_guess_version`'s
`"unknown HTTP version"` convention.
* Checked `HTTP.make()` for the same file/data mistake: it has none, but a
separate, pre-existing bug (`protocol.make(**kwargs)` calls an instance
method unbound on the class) is out of scope here and left unfixed.
Adds a regression test per fix: one pinning the real routing-type-number
message text (a bare `ProtocolError` assertion would not have caught this),
and two covering the explicit `version=1`/`version=2` HTTP paths against
real bytes and against a malformed payload.
Suite 927 passed / 20 skipped / 1248 subtests passed on this branch. mypy
clean on both changed modules.
Closes #442
Closes #447
Summary
Two small, independent, well-diagnosed defects.
#442 -- IPv6-Route diagnostics print
<class 'type'>pcapkit/protocols/internet/ipv6_route.py's three_read_data_type_*methods(
_read_data_type_src:462,_read_data_type_2:506,_read_data_type_rpl:546)raised
ProtocolError(f'... [TypeNo {type}] ...'), and none of the threesignatures binds a
typeparameter, so{type}resolved to the builtintypeand every message read[TypeNo <class 'type'>]instead of the routingtype number.
Before (measured on this branch before the fix):
Fix: use
header.type, which is already in scope with the value wanted(the read dispatch at
:211looks the handler up byschema.typeand callsmeth(schema.data, header=schema)-- no signature change needed). Alsonormalises
_read_data_type_src's punctuation fromalias [TypeNo x]: ...tothe colon-before-bracket form the other two sites, and
mh.py's ten_make_opt_*sites, already use.After:
Cross-PR compatibility: #440 (merged) records these two cases in
tests/protocols/test_option_roundtrip_unit.pykeyed on the substring tuple('IPv6-Route', '[TypeNo', 'invalid format'). All three substrings arepreserved by this fix, and
tests/protocols/test_option_roundtrip_unit.pywasrun against this branch directly: 7 passed / 299 subtests passed, unaffected.
#447 -- HTTP.read's explicit version= path passes a drained buffer
pcapkit/protocols/application/http.py'sHTTP.read's explicitversion=path built the sub-protocol from
self._file, while the auto-guessing_guess_versionpath (a few lines below) builds it fromself._data. Once theouter read has already consumed
self._file, the explicit path gets a shortor empty buffer.
Before:
Fix: pass
self._dataon the explicit path too, matching_guess_version.Also wraps a still-malformed payload's escaping bare
ValueErrorin a chainedProtocolError, so a caller can catch it as a library exception (matching_guess_version's ownraise ProtocolError("unknown HTTP version")at the endof its fallback chain) rather than losing the original error.
After:
HTTP.make()was checked for the same class of mistake (a few linesbelow, as suggested) and does not have it -- it never touches
self._file/self._data. It does have a separate, pre-existing, unrelatedbug:
protocol.make(**kwargs)callsHTTPv1.make/HTTPv2.make-- bothordinary instance methods -- unbound on the class, with no
self. This raisesTypeError: HTTP.make() missing 1 required positional argument: 'self'for anyreal (non-test-double) call; the existing test suite doesn't catch it because
its fakes define
makeas@staticmethod. Left unfixed here as out of scopefor #447, which is specifically about
read().Tests
tests/protocols/internet/test_ipv6_extension_unit.py:test_ipv6_route_read_data_type_errors_report_real_routing_typeasserts theexact rendered message text (including the real type number
250), notmerely that
ProtocolErroris raised -- a bareassertRaises(ProtocolError)would not have caught this defect.
tests/protocols/application/test_http_unit.py:test_http_read_explicit_version_uses_same_buffer_as_guesspins whichbuffer object (
self._data, notself._file) reaches the sub-protocolconstructor, for both
version=1andversion=2.test_http_read_explicit_version_1_matches_guess_on_real_bytesis theliteral issue reproduction: the explicit and auto-guessed paths now parse
identically.
test_http_read_explicit_version_wraps_malformed_payloadasserts thechained
ProtocolError.All four new tests were verified to fail before their respective fix and pass
after, by toggling each fix in isolation.
Test plan
PYTHONSAFEPATH=1+ repo-rootPYTHONPATH+pcapkit.__file__printedto confirm the tree under test, per this repo's measurement convention.
Python 3.14.7, all optional runtime deps present, sample captures
regenerated via
python examples/generators/make_samples.py.mypy --config-file mypy.iniclean on both changed modules.tests/protocols/test_option_roundtrip_unit.py(from merged tests: round-trip 258 option codes from the registries, recording the 86 that cannot close the cycle #440) rundirectly against this branch: 7 passed / 299 subtests passed.
Closes #442
Closes #447