Summary
There are a few correctness issues in the parser/writer that can break valid usage patterns or produce confusing failures on malformed input:
ipv6+prefix options seems do not round-trip correctly.
Options.__setitem__ splits tuple-valued options into multiple values.
- The scanner docs say a stream only needs
.read(), but parsing also requires .tell().
- Undersized block lengths are not rejected early and can lead to misleading downstream errors.
Problems
1. TYPE_IPV6_PREFIX encode/decode is broken
In pcapng/structs.py, the ipv6+prefix option path fails on Python 3:
- Decode uses
value[16] with struct.unpack(...), but value[16] is an int, not bytes.
- Encode does
pack_ipv6(value[0]) + value[1], which tries to concatenate bytes and int.
As a result, IPv6-prefix options such as if_IPv6addr cannot round-trip correctly.
2. Tuple-valued options are corrupted by Options.__setitem__
Options.__setitem__ currently treats any iterable that is not str/bytes as a list of repeated option values.
That breaks tuple-shaped option payloads such as:
options["typed_bytes"] = (7, b"data")
Instead of storing one logical value, it stores two values, which can trigger bogus repeated-option handling or malformed output.
3. Parsing requires .tell() even though the public contract only mentions .read()
FileScanner documentation says it accepts a file-like object providing .read(), but read_bytes_padded() also calls .tell().
This means read-only/non-seekable streams that implement .read() but not .tell() fail with AttributeError.
4. Invalid short block lengths are not rejected early
If a section header or block length is smaller than the minimum legal size:
- Python may interpret a negative read size as "read the rest of the stream"
- The parser can then fail later with
StreamEmpty or TruncatedFile
This makes corruption harder to diagnose and can consume more input than intended before failing.
Expected behavior
ipv6+prefix options should decode and encode correctly.
- Tuple-valued options should be preserved as a single option value.
- Streams that provide
.read() but not .tell() should still be readable when alignment tracking is not otherwise required.
- Clearly invalid block lengths should raise
CorruptedFile immediately.
Suggested fix
- Fix
TYPE_IPV6_PREFIX decode/encode handling in pcapng/structs.py
- Make
Options.__setitem__ preserve tuple-shaped single values and only treat explicit lists as replacement of multiple values
- Make alignment checks tolerant of streams without
.tell()
- Add explicit minimum-length validation for section headers and blocks
- Add regression tests for all of the above
Affected files
Notes
- The malformed
test006.ntar fixture should still fail; that behavior is expected.
- It may also be worth replacing some public-path
assert statements with explicit exceptions, since assert is removed under python -O.
I hope I didn't write some nonsense 🙃
Summary
There are a few correctness issues in the parser/writer that can break valid usage patterns or produce confusing failures on malformed input:
ipv6+prefixoptions seems do not round-trip correctly.Options.__setitem__splits tuple-valued options into multiple values..read(), but parsing also requires.tell().Problems
1.
TYPE_IPV6_PREFIXencode/decode is brokenIn
pcapng/structs.py, theipv6+prefixoption path fails on Python 3:value[16]withstruct.unpack(...), butvalue[16]is anint, notbytes.pack_ipv6(value[0]) + value[1], which tries to concatenatebytesandint.As a result, IPv6-prefix options such as
if_IPv6addrcannot round-trip correctly.2. Tuple-valued options are corrupted by
Options.__setitem__Options.__setitem__currently treats any iterable that is notstr/bytesas a list of repeated option values.That breaks tuple-shaped option payloads such as:
Instead of storing one logical value, it stores two values, which can trigger bogus repeated-option handling or malformed output.
3. Parsing requires
.tell()even though the public contract only mentions.read()FileScannerdocumentation says it accepts a file-like object providing.read(), butread_bytes_padded()also calls.tell().This means read-only/non-seekable streams that implement
.read()but not.tell()fail withAttributeError.4. Invalid short block lengths are not rejected early
If a section header or block length is smaller than the minimum legal size:
StreamEmptyorTruncatedFileThis makes corruption harder to diagnose and can consume more input than intended before failing.
Expected behavior
ipv6+prefixoptions should decode and encode correctly..read()but not.tell()should still be readable when alignment tracking is not otherwise required.CorruptedFileimmediately.Suggested fix
TYPE_IPV6_PREFIXdecode/encode handling inpcapng/structs.pyOptions.__setitem__preserve tuple-shaped single values and only treat explicit lists as replacement of multiple values.tell()Affected files
Notes
test006.ntarfixture should still fail; that behavior is expected.assertstatements with explicit exceptions, sinceassertis removed underpython -O.I hope I didn't write some nonsense 🙃