X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=tests%2Ftest_pyderasn.py;h=f2e73b4202a0a626f762e71b94b54f94f9548aff;hb=8cc4587b4ebd0a488db45dfdf51ce8ebbf562e0b;hp=a39d125ee036d8c12259732254a11543aec88c15;hpb=521a4868199657f49e0b20973dab53730b93fd54;p=pyderasn.git diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index a39d125..f2e73b4 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -155,9 +155,11 @@ def register_class(klass): def assert_exceeding_data(self, call, junk): - if len(junk) > 0: - with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)): - call() + if len(junk) <= 0: + return + with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err: + call() + repr(err) class TestHex(TestCase): @@ -587,10 +589,10 @@ class TestBoolean(CommonMixin, TestCase): repr(obj_expled) list(obj_expled.pps()) pprint(obj_expled, big_blobs=True, with_decode_path=True) - obj_expled_encoded = obj_expled.encode() + obj_expled_hex_encoded = obj_expled.hexencode() ctx_copied = deepcopy(ctx_dummy) - obj_decoded, tail = obj_expled.decode( - obj_expled_encoded + tail_junk, + obj_decoded, tail = obj_expled.hexdecode( + obj_expled_hex_encoded + hexenc(tail_junk), offset=offset, ctx=ctx_copied, ) @@ -603,7 +605,7 @@ class TestBoolean(CommonMixin, TestCase): self.assertNotEqual(obj_decoded, obj) self.assertEqual(bool(obj_decoded), bool(obj_expled)) self.assertEqual(bool(obj_decoded), bool(obj)) - self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded) + self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded) self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl) self.assertEqual(obj_decoded.expl_tlen, len(tag_expl)) self.assertEqual( @@ -619,7 +621,7 @@ class TestBoolean(CommonMixin, TestCase): self.assertEqual(obj_decoded.expl_offset, offset) assert_exceeding_data( self, - lambda: obj_expled.decod(obj_expled_encoded + tail_junk), + lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)), tail_junk, ) @@ -1641,6 +1643,9 @@ class TestBitString(CommonMixin, TestCase): self.assertEqual(obj.lenindef, lenindef_expected) self.assertTrue(obj.bered) self.assertEqual(len(encoded), obj.tlvlen) + repr(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given( integers(min_value=0), @@ -2174,6 +2179,9 @@ class TestOctetString(CommonMixin, TestCase): self.assertEqual(obj.lenindef, lenindef_expected) self.assertTrue(obj.bered) self.assertEqual(len(encoded), obj.tlvlen) + repr(obj) + list(obj.pps()) + pprint(obj, big_blobs=True, with_decode_path=True) @given( integers(min_value=0), @@ -2819,6 +2827,28 @@ class TestObjectIdentifier(CommonMixin, TestCase): with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"): ObjectIdentifier().decode(tampered) + @given(data_strategy()) + def test_negative_arcs(self, d): + oid = list(d.draw(oid_strategy())) + if len(oid) == 2: + return + idx = d.draw(integers(min_value=3, max_value=len(oid))) + oid[idx - 1] *= -1 + if oid[idx - 1] == 0: + oid[idx - 1] = -1 + with self.assertRaises(InvalidOID): + ObjectIdentifier(tuple(oid)) + with self.assertRaises(InvalidOID): + ObjectIdentifier(".".join(str(i) for i in oid)) + + @given(data_strategy()) + def test_plused_arcs(self, d): + oid = [str(arc) for arc in d.draw(oid_strategy())] + idx = d.draw(integers(min_value=0, max_value=len(oid))) + oid[idx - 1] = "+" + oid[idx - 1] + with self.assertRaises(InvalidOID): + ObjectIdentifier(".".join(str(i) for i in oid)) + @given(data_strategy()) def test_nonnormalized_arcs(self, d): arcs = d.draw(lists( @@ -3540,14 +3570,22 @@ class TestPrintableString( ("&", {"allow_ampersand": True}), ("&*", {"allow_asterisk": True, "allow_ampersand": True}), ): - s = "hello invalid " + c + s = "hello invalid" + obj = self.base_klass(s) + for prop in kwargs.keys(): + self.assertFalse(getattr(obj, prop)) + s += c with assertRaisesRegex(self, DecodeError, "non-printable"): self.base_klass(s) self.base_klass(s, **kwargs) klass = self.base_klass(**kwargs) obj = klass(s) + for prop in kwargs.keys(): + self.assertTrue(getattr(obj, prop)) obj = copy(obj) obj(s) + for prop in kwargs.keys(): + self.assertTrue(getattr(obj, prop)) class TestTeletexString( @@ -3707,7 +3745,10 @@ class TimeMixin(object): with self.assertRaises(ObjNotReady) as err: obj.encode() repr(err.exception) - value = d.draw(datetimes(min_value=self.min_datetime)) + value = d.draw(datetimes( + min_value=self.min_datetime, + max_value=self.max_datetime, + )) obj = self.base_klass(value) self.assertTrue(obj.ready) repr(obj) @@ -4013,6 +4054,35 @@ class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase): with assertRaisesRegex(self, DecodeError, "only microsecond fractions"): GeneralizedTime(b"20010101000000.0000001Z") + def test_non_pure_integers(self): + for data in (( + # b"20000102030405Z, + b"+2000102030405Z", + b"2000+102030405Z", + b"200001+2030405Z", + b"20000102+30405Z", + b"2000010203+405Z", + b"200001020304+5Z", + b"20000102030405.+6Z", + b"20000102030405.-6Z", + b" 2000102030405Z", + b"2000 102030405Z", + b"200001 2030405Z", + b"20000102 30405Z", + b"2000010203 405Z", + b"200001020304 5Z", + b"20000102030405. 6Z", + b"200 0102030405Z", + b"20001 02030405Z", + b"2000012 030405Z", + b"200001023 0405Z", + b"20000102034 05Z", + b"2000010203045 Z", + b"20000102030405.6 Z", + )): + with self.assertRaises(DecodeError): + GeneralizedTime(data) + class TestUTCTime(TimeMixin, CommonMixin, TestCase): base_klass = UTCTime @@ -4083,6 +4153,31 @@ class TestUTCTime(TimeMixin, CommonMixin, TestCase): datetime(1991, 5, 6, 23, 45, 40, 0), ) + def test_non_pure_integers(self): + for data in (( + # b"000102030405Z", + b"+10102030405Z", + b"00+102030405Z", + b"0001+2030405Z", + b"000102+30405Z", + b"00010203+405Z", + b"0001020304+5Z", + b" 10102030405Z", + b"00 102030405Z", + b"0001 2030405Z", + b"000102 30405Z", + b"00010203 405Z", + b"0001020304 5Z", + b"1 0102030405Z", + b"001 02030405Z", + b"00012 030405Z", + b"0001023 0405Z", + b"000102034 05Z", + b"00010203045 Z", + )): + with self.assertRaises(DecodeError): + UTCTime(data) + @given(integers(min_value=0, max_value=49)) def test_pre50(self, year): self.assertEqual( @@ -5195,6 +5290,8 @@ class SeqMixing(object): t, _, lv = tag_strip(seq_encoded) _, _, v = len_decode(lv) seq_encoded_lenindef = t + LENINDEF + v + EOC + with self.assertRaises(DecodeError): + seq.decode(seq_encoded_lenindef) ctx_copied = deepcopy(ctx_dummy) ctx_copied["bered"] = True seq_decoded_lenindef, tail_lenindef = seq.decode( @@ -5915,6 +6012,8 @@ class SeqOfMixing(object): t, _, lv = tag_strip(obj_encoded) _, _, v = len_decode(lv) obj_encoded_lenindef = t + LENINDEF + v + EOC + with self.assertRaises(DecodeError): + obj.decode(obj_encoded_lenindef) obj_decoded_lenindef, tail_lenindef = obj.decode( obj_encoded_lenindef + tail_junk, ctx={"bered": True}, @@ -6279,32 +6378,33 @@ class TestOIDDefines(TestCase): min_size=len(value_names), max_size=len(value_names), )) - _schema = [ - ("type", ObjectIdentifier(defines=(((value_name_chosen,), { - oid: Integer() for oid in oids[:-1] - }),))), - ] - for i, value_name in enumerate(value_names): - _schema.append((value_name, Any(expl=tag_ctxp(i)))) + for definable_class in (Any, OctetString, BitString): + _schema = [ + ("type", ObjectIdentifier(defines=(((value_name_chosen,), { + oid: Integer() for oid in oids[:-1] + }),))), + ] + for i, value_name in enumerate(value_names): + _schema.append((value_name, definable_class(expl=tag_ctxp(i)))) - class Seq(Sequence): - schema = _schema - seq = Seq() - for value_name, value in zip(value_names, values): - seq[value_name] = Any(Integer(value).encode()) - seq["type"] = oid_chosen - seq, _ = Seq().decode(seq.encode()) - for value_name in value_names: - if value_name == value_name_chosen: - continue - self.assertIsNone(seq[value_name].defined) - if value_name_chosen in oids[:-1]: - 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 Seq(Sequence): + schema = _schema + seq = Seq() + for value_name, value in zip(value_names, values): + seq[value_name] = definable_class(Integer(value).encode()) + seq["type"] = oid_chosen + seq, _ = Seq().decode(seq.encode()) + for value_name in value_names: + if value_name == value_name_chosen: + continue + self.assertIsNone(seq[value_name].defined) + if value_name_chosen in oids[:-1]: + 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): @@ -6355,10 +6455,10 @@ class TestDefinesByPath(TestCase): (type_integered, Integer(234)), ) for t, v in pairs_input: - pair = Pair() - pair["type"] = t - pair["value"] = PairValue((Any(v),)) - pairs.append(pair) + pairs.append(Pair(( + ("type", t), + ("value", PairValue((Any(v),))), + ))) seq_inner = SeqInner() seq_inner["typeInner"] = type_innered seq_inner["valueInner"] = Any(pairs) @@ -6496,6 +6596,43 @@ class TestDefinesByPath(TestCase): decoded, _ = Outer().decode(outer.encode()) self.assertEqual(decoded["tgt"].defined[1], Integer(tgt)) + def test_remaining_data(self): + oid = ObjectIdentifier("1.2.3") + class Seq(Sequence): + schema = ( + ("oid", ObjectIdentifier(defines=((("tgt",), { + oid: Integer(), + }),))), + ("tgt", OctetString()), + ) + + seq = Seq(( + ("oid", oid), + ("tgt", OctetString(Integer(123).encode() + b"junk")), + )) + with assertRaisesRegex(self, DecodeError, "remaining data"): + Seq().decode(seq.encode()) + + def test_remaining_data_seqof(self): + oid = ObjectIdentifier("1.2.3") + class SeqOf(SetOf): + schema = OctetString() + + class Seq(Sequence): + schema = ( + ("oid", ObjectIdentifier(defines=((("tgt",), { + oid: Integer(), + }),))), + ("tgt", SeqOf()), + ) + + seq = Seq(( + ("oid", oid), + ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])), + )) + with assertRaisesRegex(self, DecodeError, "remaining data"): + Seq().decode(seq.encode()) + class TestAbsDecodePath(TestCase): @given( @@ -6503,10 +6640,9 @@ class TestAbsDecodePath(TestCase): lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple), ) def test_concat(self, decode_path, rel_path): - self.assertSequenceEqual( - abs_decode_path(decode_path, rel_path), - decode_path + rel_path, - ) + dp = abs_decode_path(decode_path, rel_path) + self.assertSequenceEqual(dp, decode_path + rel_path) + repr(dp) @given( lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),