Skip to content

Commit 3d29238

Browse files
committed
fix(pcapng): resolve byte order for a raw bytes option without self._byte set (#2353)
An option or record handed to a block maker as raw bytes has its type code read back out of those octets, in the block's byte order -- which only `_make_block_shb` and `_make_block_systemd` set. A raw option in any other block, and a raw record in an NRB, therefore raised `AttributeError: 'PCAPNG' object has no attribute '_byte'`. `make` now settles the byte order before the block maker runs, the way `pack` settles it: the section's, else the one the packet data declares, else the host's. A section header block still overrides it from its own Byte-Order Magic. Settling it here covers every block maker: `_make_block_shb` and `_make_block_systemd` settle their own, and without this the rest read an attribute that is not there. `__packet__` handed over as `None` degrades to no packet data, matching how `Schema.pack` already treats it, rather than raising a `TypeError`. Tested by a unit module: a raw option and a raw record build with no byte order set, each block parses back from its own octets and rebuilds byte for byte, the code resolved is pinned through the "only one of this option" guard in a big-endian section as well as a little-endian one, a bound section outranks a byte order the packet data declares, a byte order declared one level up inside `__packet__` is read correctly, and `__packet__=None` resolves to the host order instead of raising. Fail-without-fix: 10 test methods, 16 failures on `origin/main`.
1 parent 7886d9f commit 3d29238

2 files changed

Lines changed: 380 additions & 0 deletions

File tree

‎pcapkit/protocols/misc/pcapng.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from pcapkit.const.pcapng.verdict_type import VerdictType as Enum_VerdictType
6565
from pcapkit.const.reg.linktype import LinkType as Enum_LinkType
6666
from pcapkit.corekit.enum import EnumLookup
67+
from pcapkit.corekit.fields.byteorder import packet_byteorder
6768
from pcapkit.corekit.fields.strings import DecodedString
6869
from pcapkit.corekit.infoclass import OrderedMultiInfo
6970
from pcapkit.corekit.io import advance
@@ -1457,6 +1458,27 @@ def make(self,
14571458
reversed=type_reversed, pack=False))
14581459
self._type = type_val
14591460

1461+
# NOTE: An option or record handed over as raw octets has its type code
1462+
# read back out of them -- by ``_make_pcapng_options`` and
1463+
# ``_make_nrb_records`` -- in the byte order the block is written in. So
1464+
# the byte order has to be settled before the block maker runs, not only
1465+
# after it as ``pack`` settles it, and settled the way ``pack`` settles
1466+
# it, so that the code read matches the octets emitted. Settling it here
1467+
# covers every block maker: ``_make_block_shb`` and
1468+
# ``_make_block_systemd`` settle their own, and without this the rest
1469+
# read an attribute that is not there (#2353). A section header block
1470+
# overrides this from its own Byte-Order Magic, it being the block that
1471+
# starts the section read here.
1472+
#
1473+
# ``or {}`` rather than a ``get`` default because ``__packet__`` may be
1474+
# handed over explicitly as :data:`None`, which is what
1475+
# :meth:`Schema.pack <pcapkit.protocols.schema.schema.Schema.pack>`
1476+
# takes for "no packet data" as well.
1477+
if self._ctx is not None:
1478+
self._byte = self._ctx.section.byteorder
1479+
else:
1480+
self._byte = packet_byteorder(kwargs.get('__packet__') or {})
1481+
14601482
if isinstance(block, bytes):
14611483
block_val = block # type: bytes | Schema_BlockType
14621484
elif isinstance(block, (dict, Data_PCAPNG)):

0 commit comments

Comments
 (0)