]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - tests/test_pyderasn.py
Fix SequenceOf/SetOf BoundsError raising
[pyderasn.git] / tests / test_pyderasn.py
index c3744157344f2db548adb2fada8e5ef36700d904..c85a90a3e3e4dc737a553b3eb98aa97126e3e8f1 100644 (file)
@@ -77,6 +77,10 @@ from pyderasn import InvalidOID
 from pyderasn import InvalidValueType
 from pyderasn import len_decode
 from pyderasn import len_encode
+from pyderasn import LEN_YYMMDDHHMMSSZ
+from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
+from pyderasn import LEN_YYYYMMDDHHMMSSZ
+from pyderasn import LENINDEF
 from pyderasn import NotEnoughData
 from pyderasn import Null
 from pyderasn import NumericString
@@ -113,7 +117,6 @@ from pyderasn import VisibleString
 
 settings.register_profile("local", settings(
     deadline=5000,
-    perform_health_check=False,
 ))
 settings.load_profile("local")
 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
@@ -613,7 +616,7 @@ class TestBoolean(CommonMixin, TestCase):
         binary().filter(lambda x: not x.startswith(EOC)),
     )
     def test_ber_expl_no_eoc(self, expl, junk):
-        encoded = expl + b"\x80" + Boolean(False).encode()
+        encoded = expl + LENINDEF + Boolean(False).encode()
         with assertRaisesRegex(self, DecodeError, "no EOC"):
             Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
         obj, tail = Boolean(expl=expl).decode(
@@ -636,7 +639,7 @@ class TestBoolean(CommonMixin, TestCase):
         for value in values:
             encoded += (
                 expl +
-                b"\x80" +
+                LENINDEF +
                 Boolean(value).encode() +
                 EOC
             )
@@ -806,9 +809,19 @@ class TestInteger(CommonMixin, TestCase):
         with self.assertRaises(BoundsError) as err:
             Integer(value=values[0], bounds=(values[1], values[2]))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            Integer(bounds=(values[1], values[2])).decode(
+                Integer(values[0]).encode()
+            )
+        repr(err.exception)
         with self.assertRaises(BoundsError) as err:
             Integer(value=values[2], bounds=(values[0], values[1]))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            Integer(bounds=(values[0], values[1])).decode(
+                Integer(values[2]).encode()
+            )
+        repr(err.exception)
 
     @given(data_strategy())
     def test_call(self, d):
@@ -1477,7 +1490,7 @@ class TestBitString(CommonMixin, TestCase):
         def chunk_constructed(contents):
             return (
                 tag_encode(form=TagFormConstructed, num=3) +
-                b"\x80" +
+                LENINDEF +
                 b"".join(BitString(content).encode() for content in contents) +
                 EOC
             )
@@ -1501,7 +1514,7 @@ class TestBitString(CommonMixin, TestCase):
         bit_len_expected += chunk_last.bit_len
         encoded_indefinite = (
             tag_encode(form=TagFormConstructed, num=impl) +
-            b"\x80" +
+            LENINDEF +
             b"".join(chunks) +
             chunk_last.encode() +
             EOC
@@ -1568,7 +1581,7 @@ class TestBitString(CommonMixin, TestCase):
         bs = BitString(b"data").encode()
         with self.assertRaises(NotEnoughData) as err:
             BitString().decode(
-                tag_encode(3, form=TagFormConstructed) + b"\x80" + chunks * bs,
+                tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
                 offset=offset,
                 decode_path=decode_path,
                 ctx={"bered": True},
@@ -1606,7 +1619,7 @@ class TestBitString(CommonMixin, TestCase):
     def test_ber_indefinite_no_chunks(self, offset, decode_path):
         with assertRaisesRegex(self, DecodeError, "no chunks") as err:
             BitString().decode(
-                tag_encode(3, form=TagFormConstructed) + b"\x80" + EOC,
+                tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
                 offset=offset,
                 decode_path=decode_path,
                 ctx={"bered": True},
@@ -1628,7 +1641,7 @@ class TestBitString(CommonMixin, TestCase):
             BitString().decode(
                 (
                     tag_encode(3, form=TagFormConstructed) +
-                    b"\x80" +
+                    LENINDEF +
                     b"".join(chunks) +
                     EOC
                 ),
@@ -1759,10 +1772,20 @@ class TestOctetString(CommonMixin, TestCase):
         with self.assertRaises(BoundsError) as err:
             OctetString(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            OctetString(bounds=(bound_min, bound_max)).decode(
+                OctetString(value).encode()
+            )
+        repr(err.exception)
         value = d.draw(binary(min_size=bound_max + 1))
         with self.assertRaises(BoundsError) as err:
             OctetString(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            OctetString(bounds=(bound_min, bound_max)).decode(
+                OctetString(value).encode()
+            )
+        repr(err.exception)
 
     @given(data_strategy())
     def test_call(self, d):
@@ -1987,7 +2010,7 @@ class TestOctetString(CommonMixin, TestCase):
         def chunk_constructed(contents):
             return (
                 tag_encode(form=TagFormConstructed, num=4) +
-                b"\x80" +
+                LENINDEF +
                 b"".join(OctetString(content).encode() for content in contents) +
                 EOC
             )
@@ -2003,7 +2026,7 @@ class TestOctetString(CommonMixin, TestCase):
                 payload_expected += payload
         encoded_indefinite = (
             tag_encode(form=TagFormConstructed, num=impl) +
-            b"\x80" +
+            LENINDEF +
             b"".join(chunks) +
             EOC
         )
@@ -2052,7 +2075,7 @@ class TestOctetString(CommonMixin, TestCase):
         bs = OctetString(b"data").encode()
         with self.assertRaises(NotEnoughData) as err:
             OctetString().decode(
-                tag_encode(4, form=TagFormConstructed) + b"\x80" + chunks * bs,
+                tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
                 offset=offset,
                 decode_path=decode_path,
                 ctx={"bered": True},
@@ -2975,10 +2998,20 @@ class StringMixin(object):
         with self.assertRaises(BoundsError) as err:
             self.base_klass(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            self.base_klass(bounds=(bound_min, bound_max)).decode(
+                self.base_klass(value).encode()
+            )
+        repr(err.exception)
         value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
         with self.assertRaises(BoundsError) as err:
             self.base_klass(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            self.base_klass(bounds=(bound_min, bound_max)).decode(
+                self.base_klass(value).encode()
+            )
+        repr(err.exception)
 
     @given(data_strategy())
     def test_call(self, d):
@@ -3609,6 +3642,48 @@ class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
             datetime(2010, 1, 2, 3, 4, 5, 0),
         )
 
+    @given(
+        binary(
+            min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
+            max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
+        ),
+        binary(min_size=1, max_size=1),
+        binary(
+            min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
+            max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
+        ),
+    )
+    def test_junk(self, part0, part1, part2):
+        junk = part0 + part1 + part2
+        assume(not (set(junk) <= set(digits.encode("ascii"))))
+        with self.assertRaises(DecodeError):
+            GeneralizedTime().decode(
+                GeneralizedTime.tag_default +
+                len_encode(len(junk)) +
+                junk
+            )
+
+    @given(
+        binary(
+            min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
+            max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
+        ),
+        binary(min_size=1, max_size=1),
+        binary(
+            min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
+            max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
+        ),
+    )
+    def test_junk_dm(self, part0, part1, part2):
+        junk = part0 + part1 + part2
+        assume(not (set(junk) <= set(digits.encode("ascii"))))
+        with self.assertRaises(DecodeError):
+            GeneralizedTime().decode(
+                GeneralizedTime.tag_default +
+                len_encode(len(junk)) +
+                junk
+            )
+
 
 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
     base_klass = UTCTime
@@ -3673,6 +3748,27 @@ class TestUTCTime(TimeMixin, CommonMixin, TestCase):
             1900 + year,
         )
 
+    @given(
+        binary(
+            min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
+            max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
+        ),
+        binary(min_size=1, max_size=1),
+        binary(
+            min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
+            max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
+        ),
+    )
+    def test_junk(self, part0, part1, part2):
+        junk = part0 + part1 + part2
+        assume(not (set(junk) <= set(digits.encode("ascii"))))
+        with self.assertRaises(DecodeError):
+            UTCTime().decode(
+                UTCTime.tag_default +
+                len_encode(len(junk)) +
+                junk
+            )
+
 
 @composite
 def any_values_strategy(draw, do_expl=False):
@@ -3900,7 +3996,7 @@ class TestAny(CommonMixin, TestCase):
         chunk = Boolean(False, expl=expl).encode()
         encoded = (
             OctetString.tag_default +
-            b"\x80" +
+            LENINDEF +
             b"".join([chunk] * chunks) +
             EOC
         )
@@ -3928,12 +4024,18 @@ class TestAny(CommonMixin, TestCase):
 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
     if schema is None:
         names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
-        tags = [tag_encode(tag) for tag in draw(sets(
-            integers(min_value=0),
+        tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
+            one_of(
+                tuples(just("impl"), integers(min_value=0).map(tag_encode)),
+                tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
+            ),
             min_size=len(names),
             max_size=len(names),
         ))]
-        schema = [(name, Integer(impl=tag)) for name, tag in zip(names, tags)]
+        schema = [
+            (name, Integer(**tag_kwargs))
+            for name, tag_kwargs in zip(names, tags)
+        ]
     value = None
     if value_required or draw(booleans()):
         value = draw(tuples(
@@ -4175,8 +4277,8 @@ class TestChoice(CommonMixin, TestCase):
         self.assertEqual(obj_decoded.expl_offset, offset)
         self.assertSequenceEqual(
             obj_expled_encoded[
-                obj_decoded.value.offset - offset:
-                obj_decoded.value.offset + obj_decoded.value.tlvlen - offset
+                obj_decoded.value.fulloffset - offset:
+                obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
             ],
             obj_encoded,
         )
@@ -4650,7 +4752,7 @@ class SeqMixing(object):
 
         t, _, lv = tag_strip(seq_encoded)
         _, _, v = len_decode(lv)
-        seq_encoded_lenindef = t + b"\x80" + v + EOC
+        seq_encoded_lenindef = t + LENINDEF + v + EOC
         seq_decoded_lenindef, tail_lenindef = seq.decode(
             seq_encoded_lenindef + tail_junk,
             ctx={"bered": True},
@@ -5008,17 +5110,27 @@ class SeqOfMixing(object):
             schema = Boolean()
         bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
         bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
-        value = [Boolean()] * d.draw(integers(max_value=bound_min - 1))
+        value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
         with self.assertRaises(BoundsError) as err:
             SeqOf(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
-        value = [Boolean()] * d.draw(integers(
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            SeqOf(bounds=(bound_min, bound_max)).decode(
+                SeqOf(value).encode()
+            )
+        repr(err.exception)
+        value = [Boolean(True)] * d.draw(integers(
             min_value=bound_max + 1,
             max_value=bound_max + 10,
         ))
         with self.assertRaises(BoundsError) as err:
             SeqOf(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
+        with assertRaisesRegex(self, DecodeError, "bounds") as err:
+            SeqOf(bounds=(bound_min, bound_max)).decode(
+                SeqOf(value).encode()
+            )
+        repr(err.exception)
 
     @given(integers(min_value=1, max_value=10))
     def test_out_of_bounds(self, bound_max):
@@ -5260,7 +5372,7 @@ class SeqOfMixing(object):
 
         t, _, lv = tag_strip(obj_encoded)
         _, _, v = len_decode(lv)
-        obj_encoded_lenindef = t + b"\x80" + v + EOC
+        obj_encoded_lenindef = t + LENINDEF + v + EOC
         obj_decoded_lenindef, tail_lenindef = obj.decode(
             obj_encoded_lenindef + tail_junk,
             ctx={"bered": True},