X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=tests%2Ftest_pyderasn.py;h=68c8861597b541665432af21a22e3d543e21a38a;hb=3ad9ef9200070276702491f2bb2e3f49cba013f4;hp=0ce2b31bd0433a2b6cacbabf80542cef1b57dd27;hpb=24bd1587aa3d3ce2723043db8e81c1f56974dc09;p=pyderasn.git diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index 0ce2b31..68c8861 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -1,6 +1,6 @@ # coding: utf-8 # PyDERASN -- Python ASN.1 DER/BER codec with abstract structures -# Copyright (C) 2017-2018 Sergey Matveev +# Copyright (C) 2017-2019 Sergey Matveev # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as @@ -16,6 +16,7 @@ # License along with this program. If not, see # . +from copy import deepcopy from datetime import datetime from string import ascii_letters from string import digits @@ -81,6 +82,7 @@ from pyderasn import LEN_YYMMDDHHMMSSZ from pyderasn import LEN_YYYYMMDDHHMMSSDMZ from pyderasn import LEN_YYYYMMDDHHMMSSZ from pyderasn import LENINDEF +from pyderasn import LenIndefForm from pyderasn import NotEnoughData from pyderasn import Null from pyderasn import NumericString @@ -131,6 +133,7 @@ tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive)) decode_path_strat = lists(integers(), max_size=3).map( lambda decode_path: tuple(str(dp) for dp in decode_path) ) +ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example() class TestHex(TestCase): @@ -371,14 +374,16 @@ class TestBoolean(CommonMixin, TestCase): obj = Boolean() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = Boolean(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(booleans(), booleans(), binary(), binary()) def test_comparison(self, value1, value2, tag1, tag2): @@ -548,20 +553,26 @@ class TestBoolean(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -608,8 +619,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), @@ -617,6 +629,8 @@ class TestBoolean(CommonMixin, TestCase): ) def test_ber_expl_no_eoc(self, expl, junk): encoded = expl + LENINDEF + Boolean(False).encode() + with self.assertRaises(LenIndefForm): + Boolean(expl=expl).decode(encoded + junk) with assertRaisesRegex(self, DecodeError, "no EOC"): Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True}) obj, tail = Boolean(expl=expl).decode( @@ -624,7 +638,13 @@ 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) + repr(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given( integers(min_value=1).map(tag_ctxc), @@ -647,6 +667,8 @@ class TestBoolean(CommonMixin, TestCase): class SeqOf(SequenceOf): schema = Boolean(expl=expl) + with self.assertRaises(LenIndefForm): + SeqOf().decode(encoded) seqof, tail = SeqOf().decode(encoded, ctx={"bered": True}) self.assertSequenceEqual(tail, b"") self.assertSequenceEqual([bool(v) for v in seqof], values) @@ -657,9 +679,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,8 +693,12 @@ class TestBoolean(CommonMixin, TestCase): False, False, True, + True, ),)), ) + repr(seqof) + list(seqof.pps()) + pprint(seqof, big_blobs=True, with_decode_path=True) @composite @@ -750,14 +777,16 @@ class TestInteger(CommonMixin, TestCase): obj = Integer() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = Integer(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) hash(obj) @given(integers(), integers(), binary(), binary()) @@ -1007,20 +1036,26 @@ class TestInteger(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -1211,14 +1246,16 @@ class TestBitString(CommonMixin, TestCase): obj = BitString() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = BitString(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given( tuples(integers(min_value=0), binary()), @@ -1385,20 +1422,26 @@ class TestBitString(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -1538,8 +1581,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 +1713,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 @@ -1728,14 +1773,16 @@ class TestOctetString(CommonMixin, TestCase): obj = OctetString() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = OctetString(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(binary(), binary(), binary(min_size=1), binary(min_size=1)) def test_comparison(self, value1, value2, tag1, tag2): @@ -1956,20 +2003,26 @@ class TestOctetString(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -2047,8 +2100,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( @@ -2135,7 +2189,8 @@ class TestNull(CommonMixin, TestCase): obj = Null() self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(binary(), binary()) def test_comparison(self, tag1, tag2): @@ -2248,20 +2303,26 @@ class TestNull(CommonMixin, TestCase): _, _, optional, _decoded = values obj = klass(optional=optional, _decoded=_decoded) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -2342,14 +2403,17 @@ class TestObjectIdentifier(CommonMixin, TestCase): obj = ObjectIdentifier() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = ObjectIdentifier(value) self.assertTrue(obj.ready) + self.assertFalse(obj.ber_encoded) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) hash(obj) @given(oid_strategy(), oid_strategy(), binary(), binary()) @@ -2555,7 +2619,7 @@ class TestObjectIdentifier(CommonMixin, TestCase): self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid))) str(obj) repr(obj) - pprint(obj) + pprint(obj, big_blobs=True, with_decode_path=True) @settings(max_examples=LONG_TEST_MAX_EXAMPLES) @given( @@ -2575,20 +2639,26 @@ class TestObjectIdentifier(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -2651,6 +2721,48 @@ class TestObjectIdentifier(CommonMixin, TestCase): ObjectIdentifier((2, 999, 3)), ) + @given(data_strategy()) + def test_nonnormalized_first_arc(self, d): + tampered = ( + ObjectIdentifier.tag_default + + len_encode(2) + + b'\x80' + + ObjectIdentifier((1, 0)).encode()[-1:] + ) + obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True}) + self.assertTrue(obj.ber_encoded) + with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"): + ObjectIdentifier().decode(tampered) + + @given(data_strategy()) + def test_nonnormalized_arcs(self, d): + arcs = d.draw(lists( + integers(min_value=0, max_value=100), + min_size=1, + max_size=5, + )) + dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode() + _, tlen, lv = tag_strip(dered) + _, llen, v = len_decode(lv) + v_no_first_arc = v[1:] + idx_for_tamper = d.draw(integers( + min_value=0, + max_value=len(v_no_first_arc) - 1, + )) + tampered = list(bytearray(v_no_first_arc)) + for _ in range(d.draw(integers(min_value=1, max_value=3))): + tampered.insert(idx_for_tamper, 0x80) + tampered = bytes(bytearray(tampered)) + tampered = ( + ObjectIdentifier.tag_default + + len_encode(len(tampered)) + + tampered + ) + obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True}) + self.assertTrue(obj.ber_encoded) + with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"): + ObjectIdentifier().decode(tampered) + @composite def enumerated_values_strategy(draw, schema=None, do_expl=False): @@ -2728,14 +2840,16 @@ class TestEnumerated(CommonMixin, TestCase): obj = self.base_klass() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = self.base_klass("whatever") self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(integers(), integers(), binary(), binary()) def test_comparison(self, value1, value2, tag1, tag2): @@ -2861,20 +2975,26 @@ class TestEnumerated(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -2950,7 +3070,8 @@ class StringMixin(object): obj = self.base_klass() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) text_type(obj) with self.assertRaises(ObjNotReady) as err: obj.encode() @@ -2959,7 +3080,8 @@ class StringMixin(object): obj = self.base_klass(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) text_type(obj) @given(data_strategy()) @@ -3181,20 +3303,26 @@ class StringMixin(object): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertNotEqual(obj_decoded, obj) @@ -3222,12 +3350,15 @@ class TestUTF8String(StringMixin, CommonMixin, TestCase): base_klass = UTF8String +cyrillic_letters = text( + alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))), + min_size=1, + max_size=5, +) + + class UnicodeDecodeErrorMixin(object): - @given(text( - alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))), - min_size=1, - max_size=5, - )) + @given(cyrillic_letters) def test_unicode_decode_error(self, cyrillic_text): with self.assertRaises(DecodeError): self.base_klass(cyrillic_text) @@ -3237,12 +3368,12 @@ class TestNumericString(StringMixin, CommonMixin, TestCase): base_klass = NumericString def text_alphabet(self): - return digits + return digits + " " @given(text(alphabet=ascii_letters, min_size=1, max_size=5)) - def test_non_numeric(self, cyrillic_text): + def test_non_numeric(self, non_numeric_text): with assertRaisesRegex(self, DecodeError, "non-numeric"): - self.base_klass(cyrillic_text) + self.base_klass(non_numeric_text) @given( sets(integers(min_value=0, max_value=10), min_size=2, max_size=2), @@ -3273,6 +3404,34 @@ class TestPrintableString( ): base_klass = PrintableString + def text_alphabet(self): + return ascii_letters + digits + " '()+,-./:=?" + + @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5)) + def test_non_printable(self, non_printable_text): + with assertRaisesRegex(self, DecodeError, "non-printable"): + self.base_klass(non_printable_text) + + @given( + sets(integers(min_value=0, max_value=10), min_size=2, max_size=2), + integers(min_value=0), + decode_path_strat, + ) + def test_invalid_bounds_while_decoding(self, ints, offset, decode_path): + value, bound_min = list(sorted(ints)) + + class String(self.base_klass): + bounds = (bound_min, bound_min) + with self.assertRaises(DecodeError) as err: + String().decode( + self.base_klass(b"1" * value).encode(), + offset=offset, + decode_path=decode_path, + ) + repr(err.exception) + self.assertEqual(err.exception.offset, offset) + self.assertEqual(err.exception.decode_path, decode_path) + class TestTeletexString( UnicodeDecodeErrorMixin, @@ -3322,8 +3481,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 +3491,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 +3501,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( @@ -3415,7 +3577,8 @@ class TimeMixin(object): obj = self.base_klass() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) @@ -3423,7 +3586,8 @@ class TimeMixin(object): obj = self.base_klass(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(data_strategy()) def test_comparison(self, d): @@ -3568,20 +3732,26 @@ class TimeMixin(object): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime()) @@ -3807,14 +3977,16 @@ class TestAny(CommonMixin, TestCase): obj = Any() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) obj = Any(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(integers()) def test_basic(self, value): @@ -3830,7 +4002,8 @@ class TestAny(CommonMixin, TestCase): len(integer_encoded), ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertSequenceEqual(obj.encode(), integer_encoded) @given(binary(), binary()) @@ -3949,20 +4122,26 @@ class TestAny(CommonMixin, TestCase): _, _, optional, _decoded = values obj = klass(value=value, optional=optional, _decoded=_decoded) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertEqual(bytes(obj_decoded), bytes(obj_expled)) @@ -4000,6 +4179,12 @@ class TestAny(CommonMixin, TestCase): b"".join([chunk] * chunks) + EOC ) + with self.assertRaises(LenIndefForm): + Any().decode( + encoded + junk, + offset=offset, + decode_path=decode_path, + ) obj, tail = Any().decode( encoded + junk, offset=offset, @@ -4009,6 +4194,12 @@ 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) + repr(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) with self.assertRaises(NotEnoughData) as err: Any().decode( encoded[:-1], @@ -4019,6 +4210,47 @@ class TestAny(CommonMixin, TestCase): self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks) self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),)) + class SeqOf(SequenceOf): + schema = Boolean(expl=expl) + + class Seq(Sequence): + schema = ( + ("type", ObjectIdentifier(defines=((("value",), { + ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default), + }),))), + ("value", Any()), + ) + seq = Seq(( + ("type", ObjectIdentifier("1.2.3")), + ("value", Any(encoded)), + )) + seq_encoded = seq.encode() + seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True}) + self.assertIsNotNone(seq_decoded["value"].defined) + repr(seq_decoded) + list(seq_decoded.pps()) + pprint(seq_decoded, big_blobs=True, with_decode_path=True) + self.assertTrue(seq_decoded.bered) + self.assertFalse(seq_decoded["type"].bered) + self.assertTrue(seq_decoded["value"].bered) + + chunk = chunk[:-1] + b"\x01" + chunks = b"".join([chunk] * (chunks + 1)) + encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks + seq = Seq(( + ("type", ObjectIdentifier("1.2.3")), + ("value", Any(encoded)), + )) + seq_encoded = seq.encode() + seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True}) + self.assertIsNotNone(seq_decoded["value"].defined) + repr(seq_decoded) + list(seq_decoded.pps()) + pprint(seq_decoded, big_blobs=True, with_decode_path=True) + self.assertTrue(seq_decoded.bered) + self.assertFalse(seq_decoded["type"].bered) + self.assertTrue(seq_decoded["value"].bered) + @composite def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False): @@ -4099,7 +4331,8 @@ class TestChoice(CommonMixin, TestCase): obj = self.base_klass() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertIsNone(obj["whatever"]) with self.assertRaises(ObjNotReady) as err: obj.encode() @@ -4107,11 +4340,13 @@ class TestChoice(CommonMixin, TestCase): obj["whatever"] = Boolean() self.assertFalse(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) obj["whatever"] = Boolean(value) self.assertTrue(obj.ready) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given(booleans(), booleans()) def test_comparison(self, value1, value2): @@ -4241,20 +4476,26 @@ class TestChoice(CommonMixin, TestCase): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self.assertEqual(obj_decoded, obj_expled) self.assertEqual(obj_decoded.choice, obj_expled.choice) @@ -4556,12 +4797,14 @@ class SeqMixing(object): seq[name] = Boolean() self.assertFalse(seq.ready) repr(seq) - pprint(seq) + list(seq.pps()) + pprint(seq, big_blobs=True, with_decode_path=True) for name, value in ready.items(): seq[name] = Boolean(value) self.assertFalse(seq.ready) repr(seq) - pprint(seq) + list(seq.pps()) + pprint(seq, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: seq.encode() repr(err.exception) @@ -4569,7 +4812,8 @@ class SeqMixing(object): seq[name] = Boolean(value) self.assertTrue(seq.ready) repr(seq) - pprint(seq) + list(seq.pps()) + pprint(seq, big_blobs=True, with_decode_path=True) @given(data_strategy()) def test_call(self, d): @@ -4744,27 +4988,35 @@ class SeqMixing(object): self.assertFalse(seq.decoded) self._assert_expects(seq, expects) repr(seq) - pprint(seq) + list(seq.pps()) + pprint(seq, big_blobs=True, with_decode_path=True) self.assertTrue(seq.ready) 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) _, _, v = len_decode(lv) seq_encoded_lenindef = t + LENINDEF + v + EOC + ctx_copied = deepcopy(ctx_dummy) + ctx_copied["bered"] = True seq_decoded_lenindef, tail_lenindef = seq.decode( seq_encoded_lenindef + tail_junk, - ctx={"bered": True}, + ctx=ctx_copied, ) + del ctx_copied["bered"] + self.assertDictEqual(ctx_copied, ctx_dummy) 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): seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True}) repr(seq_decoded_lenindef) - pprint(seq_decoded_lenindef) + list(seq_decoded_lenindef.pps()) + pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True) self.assertTrue(seq_decoded_lenindef.ready) for decoded, decoded_tail, encoded in ( @@ -4873,6 +5125,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 +5155,33 @@ 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 + with self.assertRaises(DecodeError): + Seq().decode(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 +5275,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)], @@ -5107,7 +5388,8 @@ class SeqOfMixing(object): seqof.append(value) self.assertFalse(seqof.ready) repr(seqof) - pprint(seqof) + list(seqof.pps()) + pprint(seqof, big_blobs=True, with_decode_path=True) with self.assertRaises(ObjNotReady) as err: seqof.encode() repr(err.exception) @@ -5117,7 +5399,8 @@ class SeqOfMixing(object): seqof[i] = Integer(i) self.assertTrue(seqof.ready) repr(seqof) - pprint(seqof) + list(seqof.pps()) + pprint(seqof, big_blobs=True, with_decode_path=True) def test_spec_mismatch(self): class SeqOf(self.base_klass): @@ -5364,20 +5647,26 @@ class SeqOfMixing(object): _decoded=_decoded, ) repr(obj) - pprint(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) self.assertFalse(obj.expled) obj_encoded = obj.encode() obj_expled = obj(value, expl=tag_expl) self.assertTrue(obj_expled.expled) repr(obj_expled) - pprint(obj_expled) + list(obj_expled.pps()) + pprint(obj_expled, big_blobs=True, with_decode_path=True) obj_expled_encoded = obj_expled.encode() + ctx_copied = deepcopy(ctx_dummy) obj_decoded, tail = obj_expled.decode( obj_expled_encoded + tail_junk, offset=offset, + ctx=ctx_copied, ) + self.assertDictEqual(ctx_copied, ctx_dummy) repr(obj_decoded) - pprint(obj_decoded) + list(obj_decoded.pps()) + pprint(obj_decoded, big_blobs=True, with_decode_path=True) self.assertEqual(tail, tail_junk) self._test_symmetric_compare_objs(obj_decoded, obj_expled) self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded) @@ -5412,14 +5701,47 @@ 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) + list(obj_decoded_lenindef.pps()) + pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True) self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef)) with self.assertRaises(DecodeError): obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True}) 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 + with self.assertRaises(DecodeError): + SeqOf().decode(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 + with self.assertRaises(DecodeError): + SeqOf().decode(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 +5804,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], @@ -5630,8 +5953,11 @@ class TestGoMarshalVectors(TestCase): seq = Seq() seq["erste"] = PrintableString("test") self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374")) + # Asterisk is actually not allowable + PrintableString._allowable_chars |= set(b"*") seq["erste"] = PrintableString("test*") self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a")) + PrintableString._allowable_chars -= set(b"*") class Seq(Sequence): schema = ( @@ -5734,6 +6060,9 @@ class TestOIDDefines(TestCase): self.assertIsNotNone(seq[value_name_chosen].defined) self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen) self.assertIsInstance(seq[value_name_chosen].defined[1], Integer) + repr(seq) + list(seq.pps()) + pprint(seq, big_blobs=True, with_decode_path=True) class TestDefinesByPath(TestCase): @@ -5795,9 +6124,17 @@ class TestDefinesByPath(TestCase): seq_sequenced["type"] = type_sequenced seq_sequenced["value"] = OctetString(seq_inner.encode()) seq_sequenced_raw = seq_sequenced.encode() + repr(seq_sequenced) + list(seq_sequenced.pps()) + pprint(seq_sequenced, big_blobs=True, with_decode_path=True) defines_by_path = [] - seq_integered, _ = Seq().decode(seq_integered_raw) + ctx_copied = deepcopy(ctx_dummy) + seq_integered, _ = Seq().decode( + seq_integered_raw, + ctx=ctx_copied, + ) + self.assertDictEqual(ctx_copied, ctx_dummy) self.assertIsNone(seq_integered["value"].defined) defines_by_path.append( (("type",), ((("value",), { @@ -5805,34 +6142,49 @@ class TestDefinesByPath(TestCase): type_sequenced: SeqInner(), }),)) ) + ctx_copied["defines_by_path"] = defines_by_path seq_integered, _ = Seq().decode( seq_integered_raw, - ctx={"defines_by_path": defines_by_path}, + ctx=ctx_copied, ) + del ctx_copied["defines_by_path"] + self.assertDictEqual(ctx_copied, ctx_dummy) self.assertIsNotNone(seq_integered["value"].defined) self.assertEqual(seq_integered["value"].defined[0], type_integered) self.assertEqual(seq_integered["value"].defined[1], Integer(123)) self.assertTrue(seq_integered_raw[ seq_integered["value"].defined[1].offset: ].startswith(Integer(123).encode())) + repr(seq_integered) + list(seq_integered.pps()) + pprint(seq_integered, big_blobs=True, with_decode_path=True) + ctx_copied["defines_by_path"] = defines_by_path seq_sequenced, _ = Seq().decode( seq_sequenced_raw, - ctx={"defines_by_path": defines_by_path}, + ctx=ctx_copied, ) + del ctx_copied["defines_by_path"] + self.assertDictEqual(ctx_copied, ctx_dummy) self.assertIsNotNone(seq_sequenced["value"].defined) self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced) seq_inner = seq_sequenced["value"].defined[1] self.assertIsNone(seq_inner["valueInner"].defined) + repr(seq_sequenced) + list(seq_sequenced.pps()) + pprint(seq_sequenced, big_blobs=True, with_decode_path=True) defines_by_path.append(( ("value", DecodePathDefBy(type_sequenced), "typeInner"), ((("valueInner",), {type_innered: Pairs()}),), )) + ctx_copied["defines_by_path"] = defines_by_path seq_sequenced, _ = Seq().decode( seq_sequenced_raw, - ctx={"defines_by_path": defines_by_path}, + ctx=ctx_copied, ) + del ctx_copied["defines_by_path"] + self.assertDictEqual(ctx_copied, ctx_dummy) self.assertIsNotNone(seq_sequenced["value"].defined) self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced) seq_inner = seq_sequenced["value"].defined[1] @@ -5841,6 +6193,9 @@ class TestDefinesByPath(TestCase): pairs = seq_inner["valueInner"].defined[1] for pair in pairs: self.assertIsNone(pair["value"][0].defined) + repr(seq_sequenced) + list(seq_sequenced.pps()) + pprint(seq_sequenced, big_blobs=True, with_decode_path=True) defines_by_path.append(( ( @@ -5856,10 +6211,13 @@ class TestDefinesByPath(TestCase): type_octet_stringed: OctetString(), }),), )) + ctx_copied["defines_by_path"] = defines_by_path seq_sequenced, _ = Seq().decode( seq_sequenced_raw, - ctx={"defines_by_path": defines_by_path}, + ctx=ctx_copied, ) + del ctx_copied["defines_by_path"] + self.assertDictEqual(ctx_copied, ctx_dummy) self.assertIsNotNone(seq_sequenced["value"].defined) self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced) seq_inner = seq_sequenced["value"].defined[1] @@ -5869,6 +6227,9 @@ class TestDefinesByPath(TestCase): for pair_input, pair_got in zip(pairs_input, pairs_got): self.assertEqual(pair_got["value"][0].defined[0], pair_input[0]) self.assertEqual(pair_got["value"][0].defined[1], pair_input[1]) + repr(seq_sequenced) + list(seq_sequenced.pps()) + pprint(seq_sequenced, big_blobs=True, with_decode_path=True) @given(oid_strategy(), integers()) def test_simple(self, oid, tgt): @@ -5948,8 +6309,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)