Parse partial length headers correctly.
This commit is contained in:
@@ -367,30 +367,39 @@ class Header(Field):
|
||||
@length.register(bytearray)
|
||||
def length_bin(self, val):
|
||||
def _new_len(b):
|
||||
fo = b[0]
|
||||
def _parse_len(a, offset=0):
|
||||
# returns (the parsed length, size of length field, whether the length was of partial type)
|
||||
fo = a[offset]
|
||||
|
||||
if 192 > fo:
|
||||
self._len = self.bytes_to_int(b[:1])
|
||||
del b[:1]
|
||||
if 192 > fo:
|
||||
return (self.bytes_to_int(a[offset:offset + 1]), 1, False)
|
||||
|
||||
elif 224 > fo: # >= 192 is implied
|
||||
dlen = self.bytes_to_int(b[:2])
|
||||
self._len = ((dlen - (192 << 8)) & 0xFF00) + ((dlen & 0xFF) + 192)
|
||||
del b[:2]
|
||||
elif 224 > fo: # >= 192 is implied
|
||||
dlen = self.bytes_to_int(b[offset:offset + 2])
|
||||
return (((dlen - (192 << 8)) & 0xFF00) + ((dlen & 0xFF) + 192), 2, False)
|
||||
|
||||
elif 255 > fo: # pragma: no cover
|
||||
# not testable until partial body lengths actually work
|
||||
# >= 224 is implied
|
||||
# this is a partial-length header
|
||||
self._partial = True
|
||||
self._len = 1 << (fo & 0x1f)
|
||||
elif 255 > fo: # >= 224 is implied
|
||||
# this is a partial-length header
|
||||
return (1 << (fo & 0x1f), 1, True)
|
||||
|
||||
elif 255 == fo:
|
||||
self._len = self.bytes_to_int(b[1:5])
|
||||
del b[:5]
|
||||
elif 255 == fo:
|
||||
return (self.bytes_to_int(b[offset + 1:offset + 5]), 5, False)
|
||||
|
||||
else: # pragma: no cover
|
||||
raise ValueError("Malformed length: 0x{:02x}".format(fo))
|
||||
else: # pragma: no cover
|
||||
raise ValueError("Malformed length: 0x{:02x}".format(fo))
|
||||
|
||||
part_len, size, partial = _parse_len(b)
|
||||
del b[:size]
|
||||
|
||||
if partial:
|
||||
total = part_len
|
||||
while partial:
|
||||
part_len, size, partial = _parse_len(b, total)
|
||||
del b[total:total+size]
|
||||
total += part_len
|
||||
self._len = total
|
||||
else:
|
||||
self._len = part_len
|
||||
|
||||
def _old_len(b):
|
||||
if self.llen > 0:
|
||||
|
||||
@@ -40,16 +40,12 @@ def binload(f):
|
||||
return buf
|
||||
|
||||
|
||||
skip_files = {'tests/testdata/packets/{:s}'.format(pkt) for pkt in ['11.partial.literal']}
|
||||
pktfiles = sorted(glob.glob('tests/testdata/packets/[0-9]*'))
|
||||
|
||||
|
||||
class TestPacket(object):
|
||||
@pytest.mark.parametrize('packet', pktfiles, ids=[os.path.basename(f) for f in pktfiles])
|
||||
def test_load(self, packet):
|
||||
if packet in skip_files:
|
||||
pytest.skip("not implemented yet")
|
||||
|
||||
b = binload(packet) + _trailer
|
||||
_b = b[:]
|
||||
p = Packet(_b)
|
||||
@@ -59,11 +55,12 @@ class TestPacket(object):
|
||||
|
||||
# length is computed correctly
|
||||
assert p.header.length + len(p.header) == len(p)
|
||||
assert len(p) == len(b) - len(_trailer)
|
||||
assert len(p.__bytes__()) == len(b) - len(_trailer)
|
||||
if packet not in ('tests/testdata/packets/11.partial.literal',):
|
||||
assert len(p) == len(b) - len(_trailer)
|
||||
assert len(p.__bytes__()) == len(b) - len(_trailer)
|
||||
|
||||
# __bytes__ output is correct
|
||||
assert p.__bytes__() == b[:-len(_trailer)]
|
||||
# __bytes__ output is correct
|
||||
assert p.__bytes__() == b[:-len(_trailer)]
|
||||
|
||||
# instantiated class is what we expected
|
||||
if hasattr(p.header, 'version') and (p.header.tag, p.header.version) in _pclasses:
|
||||
|
||||
Reference in New Issue
Block a user