From 529183bf80e4796b3970d18e0fac490cd5865781 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 12 Sep 2018 22:54:05 +0300 Subject: [PATCH] Separate ber/ber_encoded attributes --- VERSION | 2 +- doc/examples.rst | 11 +++-- doc/news.rst | 11 +++++ pyderasn.py | 106 ++++++++++++++++++++++++++++++++--------- tests/test_pyderasn.py | 91 +++++++++++++++++++++++++++++++---- 5 files changed, 186 insertions(+), 35 deletions(-) diff --git a/VERSION b/VERSION index 5186d07..7d5c902 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0 +4.1 diff --git a/doc/examples.rst b/doc/examples.rst index 5467482..7c10dad 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -237,9 +237,9 @@ Let's parse that output, human:: :: - 52-2∞ [1,1,1054]∞ . . . . eContent: [0] EXPLICIT BER OCTET STRING 1046 bytes - ^ ^ ^ ^ - 12 13 9 10 + 52-2∞ B [1,1,1054]∞ . . . . eContent: [0] EXPLICIT BER OCTET STRING 1046 bytes + ^ ^ ^ ^ ^ + 12 13 14 9 10 :0: Offset of the object, where its DER/BER encoding begins. @@ -273,8 +273,11 @@ Let's parse that output, human:: Possible other flags like OPTIONAL and DEFAULT, if value equals to the default one, specified in the schema. :12: - Only applicable to BER encoded data. Indefinite length encoding mark. + Shows does object contains any kind of BER encoded data (possibly + Sequence holding BER-encoded underlying value). :13: + Only applicable to BER encoded data. Indefinite length encoding mark. +:14: Only applicable to BER encoded data. If object has BER-specific encoding, then ``BER`` will be shown. It does not depend on indefinite length encoding. ``EOC``, ``BOOLEAN``, ``BIT STRING``, ``OCTET STRING`` diff --git a/doc/news.rst b/doc/news.rst index dd1241d..21b73de 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -1,6 +1,17 @@ News ==== +.. _release4.1: + +4.1 +--- +* ``bered`` attribute, meaning if object has BER-specific encoding, is + renamed to ``ber_encoded`` +* ``bered`` attribute is replace with property showing if any of + underlying values are BER-encoded. If value has length indefinite + encoded explicit tag, value, if value contains BER-related encoding, + or if it contains other objects that are ``bered``, then it is ``bered`` + .. _release4.0: 4.0 diff --git a/pyderasn.py b/pyderasn.py index 2213e78..ed4071d 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -382,7 +382,7 @@ DER. But you can optionally enable BER decoding with setting ``bered`` :ref:`context ` argument to True. Indefinite lengths and constructed primitive types should be parsed successfully. -* If object is encoded in BER form (not the DER one), then ``bered`` +* If object is encoded in BER form (not the DER one), then ``ber_encoded`` attribute is set to True. Only ``BOOLEAN``, ``BIT STRING``, ``OCTET STRING``, ``SEQUENCE``, ``SET``, ``SET OF`` can contain it. * If object has an indefinite length encoding, then its ``lenindef`` @@ -391,6 +391,12 @@ constructed primitive types should be parsed successfully. contain it. * If object has an indefinite length encoded explicit tag, then ``expl_lenindef`` is set to True. +* If object has either any of BER-related encoding (explicit tag + indefinite length, object's indefinite length, BER-encoding) or any + underlying component has that kind of encoding, then ``bered`` + attribute is set to True. For example SignedData CMS can have + ``ContentInfo:content:signerInfos:*`` ``bered`` value set to True, but + ``ContentInfo:content:signerInfos:*:signedAttrs`` won't. EOC (end-of-contents) token's length is taken in advance in object's value length. @@ -922,7 +928,7 @@ class Obj(object): "vlen", "expl_lenindef", "lenindef", - "bered", + "ber_encoded", ) def __init__( @@ -944,7 +950,7 @@ class Obj(object): self.default = None self.expl_lenindef = False self.lenindef = False - self.bered = False + self.ber_encoded = False @property def ready(self): # pragma: no cover @@ -952,6 +958,12 @@ class Obj(object): """ raise NotImplementedError() + @property + def bered(self): + """Is either object or any elements inside is BER encoded? + """ + return self.expl_lenindef or self.lenindef or self.ber_encoded + def _assert_ready(self): if not self.ready: raise ObjNotReady(self.__class__.__name__) @@ -1170,6 +1182,7 @@ class Obj(object): tlen=1, llen=1, vlen=0, + ber_encoded=True, bered=True, ) if self.expl_lenindef: @@ -1181,6 +1194,7 @@ class Obj(object): tlen=1, llen=1, vlen=0, + ber_encoded=True, bered=True, ) @@ -1232,6 +1246,7 @@ PP = namedtuple("PP", ( "expl_vlen", "expl_lenindef", "lenindef", + "ber_encoded", "bered", )) @@ -1256,6 +1271,7 @@ def _pp( expl_vlen=None, expl_lenindef=False, lenindef=False, + ber_encoded=False, bered=False, ): return PP( @@ -1278,6 +1294,7 @@ def _pp( expl_vlen, expl_lenindef, lenindef, + ber_encoded, bered, ) @@ -1305,7 +1322,9 @@ def pp_console_row( ), LENINDEF_PP_CHAR if pp.expl_lenindef else " ", ) - cols.append(_colourize(col, "red", with_colours, ())) + col = _colourize(col, "red", with_colours, ()) + col += _colourize("B", "red", with_colours) if pp.bered else " " + cols.append(col) col = "[%d,%d,%4d]%s" % ( pp.tlen, pp.llen, @@ -1342,7 +1361,7 @@ def pp_console_row( cols.append(_colourize(col, "blue", with_colours)) if pp.asn1_type_name.replace(" ", "") != pp.obj_name.upper(): cols.append(_colourize(pp.obj_name, "magenta", with_colours)) - if pp.bered: + if pp.ber_encoded: cols.append(_colourize("BER", "red", with_colours)) cols.append(_colourize(pp.asn1_type_name, "cyan", with_colours)) if pp.value is not None: @@ -1373,7 +1392,7 @@ def pp_console_row( def pp_console_blob(pp, decode_path_len_decrease=0): - cols = [" " * len("XXXXXYYZ [X,X,XXXX]Z")] + cols = [" " * len("XXXXXYYZZ [X,X,XXXX]Z")] decode_path_len = len(pp.decode_path) - decode_path_len_decrease if decode_path_len > 0: cols.append(" ." * (decode_path_len + 1)) @@ -1605,14 +1624,14 @@ class Boolean(Obj): offset=offset, ) first_octet = byte2int(v) - bered = False + ber_encoded = False if first_octet == 0: value = False elif first_octet == 0xFF: value = True elif ctx.get("bered", False): value = True - bered = True + ber_encoded = True else: raise DecodeError( "unacceptable Boolean value", @@ -1628,7 +1647,7 @@ class Boolean(Obj): optional=self.optional, _decoded=(offset, 1, 1), ) - obj.bered = bered + obj.ber_encoded = ber_encoded return obj, v[1:] def __repr__(self): @@ -1653,6 +1672,7 @@ class Boolean(Obj): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, + ber_encoded=self.ber_encoded, bered=self.bered, ) for pp in self.pps_lenindef(decode_path): @@ -1979,6 +1999,7 @@ class Integer(Obj): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, + bered=self.bered, ) for pp in self.pps_lenindef(decode_path): yield pp @@ -2402,7 +2423,7 @@ class BitString(Obj): _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) obj.lenindef = lenindef - obj.bered = True + obj.ber_encoded = True return obj, (v[EOC_LEN:] if lenindef else v) raise TagMismatch( klass=self.__class__, @@ -2441,6 +2462,7 @@ class BitString(Obj): expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, lenindef=self.lenindef, + ber_encoded=self.ber_encoded, bered=self.bered, ) defined_by, defined = self.defined or (None, None) @@ -2758,7 +2780,7 @@ class OctetString(Obj): offset=offset, ) obj.lenindef = lenindef - obj.bered = True + obj.ber_encoded = True return obj, (v[EOC_LEN:] if lenindef else v) raise TagMismatch( klass=self.__class__, @@ -2790,6 +2812,7 @@ class OctetString(Obj): expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, lenindef=self.lenindef, + ber_encoded=self.ber_encoded, bered=self.bered, ) defined_by, defined = self.defined or (None, None) @@ -2930,6 +2953,7 @@ class Null(Obj): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, + bered=self.bered, ) for pp in self.pps_lenindef(decode_path): yield pp @@ -3221,6 +3245,7 @@ class ObjectIdentifier(Obj): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, + bered=self.bered, ) for pp in self.pps_lenindef(decode_path): yield pp @@ -3446,6 +3471,8 @@ class CommonString(OctetString): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, + ber_encoded=self.ber_encoded, + bered=self.bered, ) for pp in self.pps_lenindef(decode_path): yield pp @@ -3648,6 +3675,8 @@ class UTCTime(CommonString): expl_llen=self.expl_llen if self.expled else None, expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, + ber_encoded=self.ber_encoded, + bered=self.bered, ) for pp in self.pps_lenindef(decode_path): yield pp @@ -3846,6 +3875,13 @@ class Choice(Obj): def ready(self): return self._value is not None and self._value[1].ready + @property + def bered(self): + return self.expl_lenindef or ( + (self._value is not None) and + self._value[1].bered + ) + def copy(self): obj = self.__class__(schema=self.specs) obj._expl = self._expl @@ -3963,7 +3999,7 @@ class Choice(Obj): ) obj._value = (choice, value) obj.lenindef = value.lenindef - obj.bered = value.bered + obj.ber_encoded = value.ber_encoded return obj, tail def __repr__(self): @@ -3988,6 +4024,7 @@ class Choice(Obj): vlen=self.vlen, expl_lenindef=self.expl_lenindef, lenindef=self.lenindef, + ber_encoded=self.ber_encoded, bered=self.bered, ) if self.ready: @@ -4077,6 +4114,14 @@ class Any(Obj): def ready(self): return self._value is not None + @property + def bered(self): + if self.expl_lenindef or self.lenindef: + return True + if self.defined is None: + return False + return self.defined[1].bered + def copy(self): obj = self.__class__() obj._value = self._value @@ -4211,6 +4256,7 @@ class Any(Obj): expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, lenindef=self.lenindef, + bered=self.bered, ) defined_by, defined = self.defined or (None, None) if defined_by is not None: @@ -4408,6 +4454,12 @@ class Sequence(Obj): return False return True + @property + def bered(self): + if self.expl_lenindef or self.lenindef or self.ber_encoded: + return True + return any(value.bered for value in self._value.values()) + def copy(self): obj = self.__class__(schema=self.specs) obj.tag = self.tag @@ -4542,7 +4594,7 @@ class Sequence(Obj): vlen = 0 sub_offset = offset + tlen + llen values = {} - bered = False + ber_encoded = False ctx_allow_default_values = ctx.get("allow_default_values", False) for name, spec in self.specs.items(): if spec.optional and ( @@ -4617,7 +4669,7 @@ class Sequence(Obj): v = v_tail if spec.default is not None and value == spec.default: if ctx_bered or ctx_allow_default_values: - bered = True + ber_encoded = True else: raise DecodeError( "DEFAULT value met", @@ -4667,7 +4719,7 @@ class Sequence(Obj): ) obj._value = values obj.lenindef = lenindef - obj.bered = bered + obj.ber_encoded = ber_encoded return obj, tail def __repr__(self): @@ -4699,6 +4751,8 @@ class Sequence(Obj): expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, lenindef=self.lenindef, + ber_encoded=self.ber_encoded, + bered=self.bered, ) for name in self.specs: value = self._value.get(name) @@ -4782,7 +4836,7 @@ class Set(Sequence): vlen = 0 sub_offset = offset + tlen + llen values = {} - bered = False + ber_encoded = False ctx_allow_default_values = ctx.get("allow_default_values", False) ctx_allow_unordered_set = ctx.get("allow_unordered_set", False) value_prev = memoryview(v[:0]) @@ -4820,7 +4874,7 @@ class Set(Sequence): value_len = value.fulllen if value_prev.tobytes() > v[:value_len].tobytes(): if ctx_bered or ctx_allow_unordered_set: - bered = True + ber_encoded = True else: raise DecodeError( "unordered " + self.asn1_type_name, @@ -4831,7 +4885,7 @@ class Set(Sequence): if spec.default is None or value != spec.default: pass elif ctx_bered or ctx_allow_default_values: - bered = True + ber_encoded = True else: raise DecodeError( "DEFAULT value met", @@ -4870,7 +4924,7 @@ class Set(Sequence): decode_path=decode_path, offset=offset, ) - obj.bered = bered + obj.ber_encoded = ber_encoded return obj, tail @@ -4969,6 +5023,12 @@ class SequenceOf(Obj): def ready(self): return all(v.ready for v in self._value) + @property + def bered(self): + if self.expl_lenindef or self.lenindef or self.ber_encoded: + return True + return any(v.bered for v in self._value) + def copy(self): obj = self.__class__(schema=self.spec) obj._bound_min = self._bound_min @@ -5107,7 +5167,7 @@ class SequenceOf(Obj): _value = [] ctx_allow_unordered_set = ctx.get("allow_unordered_set", False) value_prev = memoryview(v[:0]) - bered = False + ber_encoded = False spec = self.spec while len(v) > 0: if lenindef and v[:EOC_LEN].tobytes() == EOC: @@ -5124,7 +5184,7 @@ class SequenceOf(Obj): if ordering_check: if value_prev.tobytes() > v[:value_len].tobytes(): if ctx_bered or ctx_allow_unordered_set: - bered = True + ber_encoded = True else: raise DecodeError( "unordered " + self.asn1_type_name, @@ -5165,7 +5225,7 @@ class SequenceOf(Obj): ) obj.lenindef = True tail = v[EOC_LEN:] - obj.bered = bered + obj.ber_encoded = ber_encoded return obj, tail def __repr__(self): @@ -5193,6 +5253,8 @@ class SequenceOf(Obj): expl_vlen=self.expl_vlen if self.expled else None, expl_lenindef=self.expl_lenindef, lenindef=self.lenindef, + ber_encoded=self.ber_encoded, + bered=self.bered, ) for i, value in enumerate(self._value): yield value.pps(decode_path=decode_path + (str(i),)) diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index 0ce2b31..dd3506b 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -608,8 +608,9 @@ class TestBoolean(CommonMixin, TestCase): ctx={"bered": True}, ) self.assertTrue(bool(obj)) - self.assertTrue(obj.bered) + self.assertTrue(obj.ber_encoded) self.assertFalse(obj.lenindef) + self.assertTrue(obj.bered) @given( integers(min_value=1).map(tag_ctxc), @@ -624,6 +625,9 @@ class TestBoolean(CommonMixin, TestCase): ctx={"bered": True}, ) self.assertTrue(obj.expl_lenindef) + self.assertFalse(obj.lenindef) + self.assertFalse(obj.ber_encoded) + self.assertTrue(obj.bered) self.assertSequenceEqual(tail, junk) @given( @@ -657,9 +661,10 @@ class TestBoolean(CommonMixin, TestCase): v.expl_tlvlen, v.expl_tlen, v.expl_llen, - v.bered, + v.ber_encoded, v.lenindef, v.expl_lenindef, + v.bered, ) for v in seqof ), set((( @@ -670,6 +675,7 @@ class TestBoolean(CommonMixin, TestCase): False, False, True, + True, ),)), ) @@ -1538,8 +1544,9 @@ class TestBitString(CommonMixin, TestCase): self.assertSequenceEqual(tail, junk) self.assertEqual(obj.bit_len, bit_len_expected) self.assertSequenceEqual(bytes(obj), payload_expected) - self.assertTrue(obj.bered) + self.assertTrue(obj.ber_encoded) self.assertEqual(obj.lenindef, lenindef_expected) + self.assertTrue(obj.bered) self.assertEqual(len(encoded), obj.tlvlen) @given( @@ -1669,8 +1676,9 @@ class TestBitString(CommonMixin, TestCase): ) self.assertSequenceEqual(tail, b"") self.assertEqual(obj, vector) - self.assertTrue(obj.bered) + self.assertTrue(obj.ber_encoded) self.assertTrue(obj.lenindef) + self.assertTrue(obj.bered) @composite @@ -2047,8 +2055,9 @@ class TestOctetString(CommonMixin, TestCase): ) self.assertSequenceEqual(tail, junk) self.assertSequenceEqual(bytes(obj), payload_expected) - self.assertTrue(obj.bered) + self.assertTrue(obj.ber_encoded) self.assertEqual(obj.lenindef, lenindef_expected) + self.assertTrue(obj.bered) self.assertEqual(len(encoded), obj.tlvlen) @given( @@ -3322,8 +3331,9 @@ class TestVisibleString( obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573")) self.assertSequenceEqual(tail, b"") self.assertEqual(str(obj), "Jones") - self.assertFalse(obj.bered) + self.assertFalse(obj.ber_encoded) self.assertFalse(obj.lenindef) + self.assertFalse(obj.bered) obj, tail = VisibleString().decode( hexdec("3A0904034A6F6E04026573"), @@ -3331,8 +3341,9 @@ class TestVisibleString( ) self.assertSequenceEqual(tail, b"") self.assertEqual(str(obj), "Jones") - self.assertTrue(obj.bered) + self.assertTrue(obj.ber_encoded) self.assertFalse(obj.lenindef) + self.assertTrue(obj.bered) obj, tail = VisibleString().decode( hexdec("3A8004034A6F6E040265730000"), @@ -3340,8 +3351,9 @@ class TestVisibleString( ) self.assertSequenceEqual(tail, b"") self.assertEqual(str(obj), "Jones") - self.assertTrue(obj.bered) + self.assertTrue(obj.ber_encoded) self.assertTrue(obj.lenindef) + self.assertTrue(obj.bered) class TestGeneralString( @@ -4009,6 +4021,9 @@ class TestAny(CommonMixin, TestCase): self.assertSequenceEqual(tail, junk) self.assertEqual(obj.offset, offset) self.assertEqual(obj.tlvlen, len(encoded)) + self.assertTrue(obj.lenindef) + self.assertFalse(obj.ber_encoded) + self.assertTrue(obj.bered) with self.assertRaises(NotEnoughData) as err: Any().decode( encoded[:-1], @@ -4749,6 +4764,7 @@ class SeqMixing(object): seq_encoded = seq.encode() seq_decoded, tail = seq.decode(seq_encoded + tail_junk) self.assertFalse(seq_decoded.lenindef) + self.assertFalse(seq_decoded.ber_encoded) self.assertFalse(seq_decoded.bered) t, _, lv = tag_strip(seq_encoded) @@ -4759,6 +4775,7 @@ class SeqMixing(object): ctx={"bered": True}, ) self.assertTrue(seq_decoded_lenindef.lenindef) + self.assertTrue(seq_decoded_lenindef.bered) with self.assertRaises(DecodeError): seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True}) with self.assertRaises(DecodeError): @@ -4873,6 +4890,7 @@ class SeqMixing(object): seq_with_default.decode(seq_encoded) for ctx in ({"bered": True}, {"allow_default_values": True}): seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx) + self.assertTrue(seq_decoded.ber_encoded) self.assertTrue(seq_decoded.bered) for name, value in _schema: self.assertEqual(seq_decoded[name], seq_with_default[name]) @@ -4902,6 +4920,31 @@ class SeqMixing(object): with self.assertRaises(TagMismatch): seq_missing.decode(seq_encoded) + @given(data_strategy()) + def test_bered(self, d): + class Seq(self.base_klass): + schema = (("underlying", Boolean()),) + encoded = Boolean.tag_default + len_encode(1) + b"\x01" + encoded = Seq.tag_default + len_encode(len(encoded)) + encoded + decoded, _ = Seq().decode(encoded, ctx={"bered": True}) + self.assertFalse(decoded.ber_encoded) + self.assertFalse(decoded.lenindef) + self.assertTrue(decoded.bered) + + class Seq(self.base_klass): + schema = (("underlying", OctetString()),) + encoded = ( + tag_encode(form=TagFormConstructed, num=4) + + LENINDEF + + OctetString(b"whatever").encode() + + EOC + ) + encoded = Seq.tag_default + len_encode(len(encoded)) + encoded + decoded, _ = Seq().decode(encoded, ctx={"bered": True}) + self.assertFalse(decoded.ber_encoded) + self.assertFalse(decoded.lenindef) + self.assertTrue(decoded.bered) + class TestSequence(SeqMixing, CommonMixin, TestCase): base_klass = Sequence @@ -4995,6 +5038,7 @@ class TestSet(SeqMixing, CommonMixin, TestCase): seq.decode(seq_encoded) for ctx in ({"bered": True}, {"allow_unordered_set": True}): seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx) + self.assertTrue(seq_decoded.ber_encoded) self.assertTrue(seq_decoded.bered) self.assertSequenceEqual( [bytes(seq_decoded[str(i)]) for i, t in enumerate(tags)], @@ -5412,6 +5456,7 @@ class SeqOfMixing(object): ctx={"bered": True}, ) self.assertTrue(obj_decoded_lenindef.lenindef) + self.assertTrue(obj_decoded_lenindef.bered) repr(obj_decoded_lenindef) pprint(obj_decoded_lenindef) self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef)) @@ -5420,6 +5465,33 @@ class SeqOfMixing(object): with self.assertRaises(DecodeError): obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True}) + @given(data_strategy()) + def test_bered(self, d): + class SeqOf(self.base_klass): + schema = Boolean() + encoded = Boolean(False).encode() + encoded += Boolean.tag_default + len_encode(1) + b"\x01" + encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded + decoded, _ = SeqOf().decode(encoded, ctx={"bered": True}) + self.assertFalse(decoded.ber_encoded) + self.assertFalse(decoded.lenindef) + self.assertTrue(decoded.bered) + + class SeqOf(self.base_klass): + schema = OctetString() + encoded = OctetString(b"whatever").encode() + encoded += ( + tag_encode(form=TagFormConstructed, num=4) + + LENINDEF + + OctetString(b"whatever").encode() + + EOC + ) + encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded + decoded, _ = SeqOf().decode(encoded, ctx={"bered": True}) + self.assertFalse(decoded.ber_encoded) + self.assertFalse(decoded.lenindef) + self.assertTrue(decoded.bered) + class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase): class SeqOf(SequenceOf): @@ -5482,6 +5554,7 @@ class TestSetOf(SeqOfMixing, CommonMixin, TestCase): for ctx in ({"bered": True}, {"allow_unordered_set": True}): seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx) + self.assertTrue(seq_decoded.ber_encoded) self.assertTrue(seq_decoded.bered) self.assertSequenceEqual( [obj.encode() for obj in seq_decoded], @@ -5948,8 +6021,10 @@ class TestStrictDefaultExistence(TestCase): with assertRaisesRegex(self, DecodeError, "DEFAULT value met"): seq.decode(raw) decoded, _ = seq.decode(raw, ctx={"allow_default_values": True}) + self.assertTrue(decoded.ber_encoded) self.assertTrue(decoded.bered) decoded, _ = seq.decode(raw, ctx={"bered": True}) + self.assertTrue(decoded.ber_encoded) self.assertTrue(decoded.bered) -- 2.44.0