From: Sergey Matveev Date: Sun, 20 May 2018 08:53:59 +0000 (+0300) Subject: Separate BERed and LenIndefinited properties X-Git-Tag: 3.7~20 X-Git-Url: http://www.git.cypherpunks.ru/?p=pyderasn.git;a=commitdiff_plain;h=05f030d41edef47ea94f68b9e770590d96e743af Separate BERed and LenIndefinited properties --- diff --git a/pyderasn.py b/pyderasn.py index a048f4d..c8e29e3 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -849,8 +849,9 @@ class Obj(object): "offset", "llen", "vlen", + "lenindef", + "expl_lenindef", "bered", - "expl_bered", ) def __init__( @@ -872,8 +873,9 @@ class Obj(object): self.optional = optional self.offset, self.llen, self.vlen = _decoded self.default = None + self.lenindef = False + self.expl_lenindef = False self.bered = False - self.expl_bered = False @property def ready(self): # pragma: no cover @@ -1012,7 +1014,7 @@ class Obj(object): offset=offset, ) obj.vlen += EOC_LEN - obj.expl_bered = True + obj.expl_lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -1054,7 +1056,7 @@ class Obj(object): @property def expl_llen(self): - if self.expl_bered: + if self.expl_lenindef: return 1 return len(len_encode(self.tlvlen)) @@ -2121,12 +2123,12 @@ class BitString(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) except LenIndefiniteForm: llen, l, v = 1, 0, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -2141,7 +2143,7 @@ class BitString(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected and l == 0: + if not lenindef and l == 0: raise NotEnoughData( "zero length", klass=self.__class__, @@ -2152,7 +2154,7 @@ class BitString(Obj): sub_offset = offset + tlen + llen vlen = 0 while True: - if eoc_expected: + if lenindef: if v[:EOC_LEN].tobytes() == EOC: break else: @@ -2210,10 +2212,11 @@ class BitString(Obj): default=self.default, optional=self.optional, _specs=self.specs, - _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)), + _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) + obj.lenindef = lenindef obj.bered = True - return obj, v[EOC_LEN if eoc_expected else 0:] + return obj, (v[EOC_LEN:] if lenindef else v) raise TagMismatch( klass=self.__class__, decode_path=decode_path, @@ -2472,12 +2475,12 @@ class OctetString(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) except LenIndefiniteForm: llen, l, v = 1, 0, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -2492,7 +2495,7 @@ class OctetString(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected and l == 0: + if not lenindef and l == 0: raise NotEnoughData( "zero length", klass=self.__class__, @@ -2503,7 +2506,7 @@ class OctetString(Obj): sub_offset = offset + tlen + llen vlen = 0 while True: - if eoc_expected: + if lenindef: if v[:EOC_LEN].tobytes() == EOC: break else: @@ -2548,7 +2551,7 @@ class OctetString(Obj): expl=self._expl, default=self.default, optional=self.optional, - _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)), + _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) except DecodeError as err: raise DecodeError( @@ -2564,8 +2567,9 @@ class OctetString(Obj): decode_path=decode_path, offset=offset, ) + obj.lenindef = lenindef obj.bered = True - return obj, v[EOC_LEN if eoc_expected else 0:] + return obj, (v[EOC_LEN:] if lenindef else v) raise TagMismatch( klass=self.__class__, decode_path=decode_path, @@ -3915,7 +3919,7 @@ class Any(Obj): optional=self.optional, _decoded=(offset, 0, tlvlen), ) - obj.bered = True + obj.lenindef = True obj.tag = t return obj, v[EOC_LEN:] else: @@ -4275,7 +4279,7 @@ class Sequence(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) except LenIndefiniteForm as err: @@ -4287,7 +4291,7 @@ class Sequence(Obj): offset=offset, ) l, llen, v = 0, 1, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -4302,14 +4306,14 @@ class Sequence(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected: + if not lenindef: v, tail = v[:l], v[l:] vlen = 0 sub_offset = offset + tlen + llen values = {} for name, spec in self.specs.items(): if spec.optional and ( - (eoc_expected and v[:EOC_LEN].tobytes() == EOC) or + (lenindef and v[:EOC_LEN].tobytes() == EOC) or len(v) == 0 ): continue @@ -4403,7 +4407,7 @@ class Sequence(Obj): abs_decode_path(sub_decode_path[:-1], rel_path), (value, defined), )) - if eoc_expected: + if lenindef: if v[:EOC_LEN].tobytes() != EOC: raise DecodeError( "no EOC", @@ -4429,8 +4433,7 @@ class Sequence(Obj): _decoded=(offset, llen, vlen), ) obj._value = values - if eoc_expected: - obj.bered = True + obj.lenindef = lenindef return obj, tail def __repr__(self): @@ -4501,7 +4504,7 @@ class Set(Sequence): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) except LenIndefiniteForm as err: @@ -4513,7 +4516,7 @@ class Set(Sequence): offset=offset, ) l, llen, v = 0, 1, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -4527,14 +4530,14 @@ class Set(Sequence): klass=self.__class__, offset=offset, ) - if not eoc_expected: + if not lenindef: v, tail = v[:l], v[l:] vlen = 0 sub_offset = offset + tlen + llen values = {} specs_items = self.specs.items while len(v) > 0: - if eoc_expected and v[:EOC_LEN].tobytes() == EOC: + if lenindef and v[:EOC_LEN].tobytes() == EOC: break for name, spec in specs_items(): sub_decode_path = decode_path + (name,) @@ -4576,7 +4579,7 @@ class Set(Sequence): expl=self._expl, default=self.default, optional=self.optional, - _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)), + _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) obj._value = values if not obj.ready: @@ -4586,10 +4589,8 @@ class Set(Sequence): decode_path=decode_path, offset=offset, ) - if eoc_expected: - obj.bered = True - tail = v[EOC_LEN:] - return obj, tail + obj.lenindef = lenindef + return obj, (v[EOC_LEN:] if lenindef else tail) class SequenceOf(Obj): @@ -4790,7 +4791,7 @@ class SequenceOf(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) except LenIndefiniteForm as err: @@ -4802,7 +4803,7 @@ class SequenceOf(Obj): offset=offset, ) l, llen, v = 0, 1, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -4817,14 +4818,14 @@ class SequenceOf(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected: + if not lenindef: v, tail = v[:l], v[l:] vlen = 0 sub_offset = offset + tlen + llen _value = [] spec = self.spec while len(v) > 0: - if eoc_expected and v[:EOC_LEN].tobytes() == EOC: + if lenindef and v[:EOC_LEN].tobytes() == EOC: break value, v_tail = spec.decode( v, @@ -4848,10 +4849,8 @@ class SequenceOf(Obj): optional=self.optional, _decoded=(offset, llen, vlen), ) - if eoc_expected: - obj.bered = True - tail = v[EOC_LEN:] - return obj, tail + obj.lenindef = lenindef + return obj, (v[EOC_LEN:] if lenindef else tail) def __repr__(self): return "%s[%s]" % ( diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index faa8569..10ad675 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -607,6 +607,7 @@ class TestBoolean(CommonMixin, TestCase): ) self.assertTrue(bool(obj)) self.assertTrue(obj.bered) + self.assertFalse(obj.lenindef) @given( integers(min_value=1).map(tag_ctxc), @@ -633,8 +634,26 @@ class TestBoolean(CommonMixin, TestCase): self.assertSequenceEqual(tail, b"") self.assertSequenceEqual([bool(v) for v in seqof], values) self.assertSetEqual( - set((v.tlvlen, v.expl_tlvlen, v.expl_tlen, v.expl_llen) for v in seqof), - set(((3 + EOC_LEN, len(expl) + 1 + 3 + EOC_LEN, len(expl), 1),)), + set( + ( + v.tlvlen, + v.expl_tlvlen, + v.expl_tlen, + v.expl_llen, + v.bered, + v.lenindef, + v.expl_lenindef, + ) for v in seqof + ), + set((( + 3 + EOC_LEN, + len(expl) + 1 + 3 + EOC_LEN, + len(expl), + 1, + False, + False, + True, + ),)), ) @@ -1485,7 +1504,10 @@ class TestBitString(CommonMixin, TestCase): ) with assertRaisesRegex(self, DecodeError, "unallowed BER"): BitString(impl=tag_encode(impl)).decode(encoded_indefinite) - for encoded in (encoded_indefinite, encoded_definite): + for lenindef_expected, encoded in ( + (True, encoded_indefinite), + (False, encoded_definite), + ): obj, tail = BitString(impl=tag_encode(impl)).decode( encoded, ctx={"bered": True} ) @@ -1493,6 +1515,7 @@ class TestBitString(CommonMixin, TestCase): self.assertEqual(obj.bit_len, bit_len_expected) self.assertSequenceEqual(bytes(obj), payload_expected) self.assertTrue(obj.bered) + self.assertEqual(obj.lenindef, lenindef_expected) self.assertEqual(len(encoded), obj.tlvlen) def test_x690_vector(self): @@ -1507,6 +1530,8 @@ class TestBitString(CommonMixin, TestCase): ) self.assertSequenceEqual(tail, b"") self.assertEqual(obj, vector) + self.assertTrue(obj.bered) + self.assertTrue(obj.lenindef) @composite @@ -1865,13 +1890,17 @@ class TestOctetString(CommonMixin, TestCase): ) with assertRaisesRegex(self, DecodeError, "unallowed BER"): OctetString(impl=tag_encode(impl)).decode(encoded_indefinite) - for encoded in (encoded_indefinite, encoded_definite): + for lenindef_expected, encoded in ( + (True, encoded_indefinite), + (False, encoded_definite), + ): obj, tail = OctetString(impl=tag_encode(impl)).decode( encoded, ctx={"bered": True} ) self.assertSequenceEqual(tail, b"") self.assertSequenceEqual(bytes(obj), payload_expected) self.assertTrue(obj.bered) + self.assertEqual(obj.lenindef, lenindef_expected) self.assertEqual(len(encoded), obj.tlvlen) @@ -3085,24 +3114,29 @@ class TestVisibleString( base_klass = VisibleString def test_x690_vector(self): - self.assertEqual( - str(VisibleString().decode(hexdec("1A054A6F6E6573"))[0]), - "Jones", - ) - self.assertEqual( - str(VisibleString().decode( - hexdec("3A0904034A6F6E04026573"), - ctx={"bered": True}, - )[0]), - "Jones", + obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573")) + self.assertSequenceEqual(tail, b"") + self.assertEqual(str(obj), "Jones") + self.assertFalse(obj.bered) + self.assertFalse(obj.lenindef) + + obj, tail = VisibleString().decode( + hexdec("3A0904034A6F6E04026573"), + ctx={"bered": True}, ) - self.assertEqual( - str(VisibleString().decode( - hexdec("3A8004034A6F6E040265730000"), - ctx={"bered": True}, - )[0]), - "Jones", + self.assertSequenceEqual(tail, b"") + self.assertEqual(str(obj), "Jones") + self.assertTrue(obj.bered) + self.assertFalse(obj.lenindef) + + obj, tail = VisibleString().decode( + hexdec("3A8004034A6F6E040265730000"), + ctx={"bered": True}, ) + self.assertSequenceEqual(tail, b"") + self.assertEqual(str(obj), "Jones") + self.assertTrue(obj.bered) + self.assertTrue(obj.lenindef) class TestGeneralString(