]> Cypherpunks.ru repositories - pyderasn.git/commitdiff
Raise copyright years master
authorSergey Matveev <stargrave@stargrave.org>
Sun, 7 Jan 2024 08:56:45 +0000 (11:56 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 7 Jan 2024 08:56:49 +0000 (11:56 +0300)
18 files changed:
PUBKEY.asc
VERSION
doc/browser.webp [new file with mode: 0644]
doc/build.log.do
doc/conf.py
doc/features.rst
doc/index.rst
doc/install.rst
doc/news.rst
doc/pprinting.png [deleted file]
doc/pprinting.webp [new file with mode: 0644]
makedist [moved from makedist.sh with 75% similarity]
pip-requirements-tests.txt
pyderasn.py
tests/test_cms.py
tests/test_crl.py
tests/test_crts.py
tests/test_pyderasn.py

index efe51130cf0c0f9b30f9fd7c99db80f4cd3757e7..0332845fedfd3ba93b95cf942cf788dabe00a6a1 100644 (file)
@@ -16,6 +16,8 @@ y8RmHsszF3sJ5wLuGk1vpSh1jgq61RUquQYJa1iE2B8fxpL6Qr+T8IR2Jan4TFIn
 vzGeBXtCD2yUIeJgSeF/3VoEq8lxJ+rwHwcsIqHF7QdqJCc7S0wviHUEEBEIAB0W
 IQTPYOiaWSMeduJjZCKuGoEJ5JhX7wUCWcLAIAAKCRCuGoEJ5JhX7+lbAP9+WNA4
 Uk0pNH5BAASabuT+zllnHZ5SqZoKWbs7bzWfogD+NWmjTfSJCr7GSZ4Suy3Vw4nn
-hUu3L6dceWUU+hAEOBw=
-=Qodb
+hUu3L6dceWUU+hAEOByIdQQQFgoAHRYhBBKtMmicZg1CaWf9dcuCBWMhB62KBQJi
+6jwUAAoJEMuCBWMhB62KYHMBAOQ6VHkVXpBrQAWCNYUEo9LZAvM2CokI6HVpJps1
+7mZNAP0RI3s/4v8N7a4b+ghbaEtxBIWWlXxqlBgDj/Rbnke0Dg==
+=0AVp
 -----END PGP PUBLIC KEY BLOCK-----
diff --git a/VERSION b/VERSION
index 28a2186428bce031c24134633c4ab80a86f11668..c3cae12bcc132c9d8c31eb702d8490ba03304ce1 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-9.1
+9.3
diff --git a/doc/browser.webp b/doc/browser.webp
new file mode 100644 (file)
index 0000000..6556f0d
Binary files /dev/null and b/doc/browser.webp differ
index 76ab32db55a77e6e8db1579a7d0c34a6f64436c7..be6a37029a5741f298df880fcc938ba7e3eaf0ac 100644 (file)
@@ -1,7 +1,7 @@
 rm -fr _build
 html=_build/html
 PYTHONPATH=.. ${PYTHON:=python} -msphinx . $html
-[ -d download ] && cp -r download $html || echo No download directory, skipping
+[ -d download ] && cp -a download $html || echo No download directory, skipping
 rm -r $html/.doctrees $html/.buildinfo
 find $html -type d -exec chmod 755 {} +
 find $html -type f -exec chmod 644 {} +
index 9061ce7568a774cd27a08c6307e9f830a98e61bc..a82a7b54f30b1ab657d87980970001d97bbeba60 100644 (file)
@@ -5,11 +5,10 @@ templates_path = ["_templates"]
 source_suffix = ".rst"
 master_doc = "index"
 project = "pyderasn"
-copyright = "2017-2021, Sergey Matveev"
+copyright = "2017-2023, Sergey Matveev"
 author = "Sergey Matveev"
 version = version
 release = version
-language = None
 exclude_patterns = ["_build"]
 pygments_style = "sphinx"
 todo_include_todos = False
index fd7bb7d71df35a275abdf52c5e8d904fa6fd62dd..5cfabee47b787f79e0072d6c33ee7fffa6dc13cf 100644 (file)
@@ -65,14 +65,14 @@ Also there is `asn1crypto <https://github.com/wbond/asn1crypto>`__.
   conveniently replace utilities like either ``dumpasn1`` or
   ``openssl asn1parse``
 
-  .. figure:: pprinting.png
+  .. figure:: pprinting.webp
      :alt: Pretty printing example output
 
      An example of pretty printed X.509 certificate with automatically
      parsed DEFINED BY fields.
 * :ref:`ASN.1 browser <browser>`
 
-  .. figure:: browser.png
+  .. figure:: browser.webp
      :alt: ASN.1 browser example
 
      An example of browser running.
index 60fadae459800965acf55dfe9eaecb7ad925aa55..b9c56a343534d7728abe5d83fbe59d261cf91a3d 100644 (file)
@@ -38,13 +38,13 @@ There are articles about its history and usage:
 * `Как я написал ASN.1 библиотеку с slots and blobs <https://m.habr.com/ru/post/444272/>`__ (on russian)
 * `Как я добавил big-data поддержку <https://m.habr.com/ru/post/498014/>`__ (on russian)
 
-.. figure:: pprinting.png
+.. figure:: pprinting.webp
    :alt: Pretty printing example output
 
    An example of pretty printed X.509 certificate with automatically
    parsed DEFINED BY fields.
 
-.. figure:: browser.png
+.. figure:: browser.webp
    :alt: ASN.1 browser example
 
    An example of browser running.
index c05ee24b6ec035d032644cb333211b57c1dfc191..057f47db616a2b1da39b69dc88edc0f9fa125cae 100644 (file)
@@ -4,11 +4,11 @@ Install
 Preferable way is to :ref:`download <download>` tarball with the
 signature from `official website <http://www.pyderasn.cypherpunks.ru/>`__::
 
-    $ [fetch|wget] http://www.pyderasn.cypherpunks.ru/download/pyderasn-9.1.tar.zst
-    $ [fetch|wget] http://www.pyderasn.cypherpunks.ru/download/pyderasn-9.1.tar.zst.sig
-    $ gpg --verify pyderasn-9.1.tar.zst.sig pyderasn-9.1.tar.zst
-    $ zstd -d < pyderasn-9.1.tar.zst | tar xf -
-    $ cd pyderasn-9.1
+    $ [fetch|wget] http://www.pyderasn.cypherpunks.ru/download/pyderasn-9.3.tar.zst
+    $ [fetch|wget] http://www.pyderasn.cypherpunks.ru/download/pyderasn-9.3.tar.zst.asc
+    $ gpg --verify pyderasn-9.3.tar.zst.asc pyderasn-9.3.tar.zst
+    $ zstd -d < pyderasn-9.3.tar.zst | tar xf -
+    $ cd pyderasn-9.3
     $ python setup.py install
     # or copy pyderasn.py (possibly termcolor.py) to your PYTHONPATH
 
@@ -16,11 +16,6 @@ signature from `official website <http://www.pyderasn.cypherpunks.ru/>`__::
 * ``urwid`` is an optional dependency used for :ref:`interactive browser <browser>`.
 * ``dateutil`` is an optional dependency used for ``.totzdatetime()`` method.
 
-You could use pip (**no** OpenPGP authentication is performed!) with PyPI::
-
-    $ echo pyderasn==9.1 --hash=sha256:TO-BE-FILLED > requirements.txt
-    $ pip install --requirement requirements.txt
-
 You have to verify downloaded tarballs integrity and authenticity to be
 sure that you retrieved trusted and untampered software. `GNU Privacy
 Guard <https://www.gnupg.org/>`__ is used for that purpose.
@@ -36,6 +31,6 @@ resources.
     uid   PyDERASN releases <pyderasn@cypherpunks.ru>
 
     $ gpg --auto-key-locate dane --locate-keys pyderasn at cypherpunks dot ru
-    $ gpg --auto-key-locate wkd --locate-keys pyderasn at cypherpunks dot ru
+    $ gpg --auto-key-locate  wkd --locate-keys pyderasn at cypherpunks dot ru
 
 .. literalinclude:: ../PUBKEY.asc
index 68d0a6e4cc12d60401f815bfd5078a73934db35e..92f0646d26c713c171976bcf27607b3f11faa949 100644 (file)
@@ -1,6 +1,22 @@
 News
 ====
 
+.. _release9.3:
+
+9.3
+---
+* CommonString's ``.memoryview()`` raises ValueError now for
+  friendliness with linters
+
+.. _release9.2:
+
+9.2
+---
+* ``keep_memoryview`` context option appeared, respected by OctetString
+  and Any objects during DER decoding. If set, then their internal
+  values will keep memoryview reference instead of full bytes copy
+* Correspondingly OctetString and Any have ``.memoryview()`` method
+
 .. _release9.1:
 
 9.1
diff --git a/doc/pprinting.png b/doc/pprinting.png
deleted file mode 100644 (file)
index 8f74110..0000000
Binary files a/doc/pprinting.png and /dev/null differ
diff --git a/doc/pprinting.webp b/doc/pprinting.webp
new file mode 100644 (file)
index 0000000..2e94c1a
Binary files /dev/null and b/doc/pprinting.webp differ
similarity index 75%
rename from makedist.sh
rename to makedist
index aaf7fb9357600225d0459185368d701cfad4ebf1..3aafd67106a83e0ec53986f3ba1477fb8b2b2ba6 100755 (executable)
+++ b/makedist
@@ -10,7 +10,7 @@ mkdir $tmp/pyderasn-"$release"
     echo pyderasn.py
     echo setup.py
     find $(perl -lane 'print $F[1]' MANIFEST.in)
-} | tar cfI - - | tar xfC - $tmp/pyderasn-"$release"
+} | tar cfT - - | tar xfC - $tmp/pyderasn-"$release"
 
 PYTHONPATH="$tmp/pyderasn-$release" redo $tmp/pyderasn-"$release"/doc/build.log
 rm -r $tmp/pyderasn-"$release"/doc/.redo $tmp/pyderasn-"$release"/doc/build.log
@@ -18,19 +18,19 @@ rm -r $tmp/pyderasn-"$release"/doc/.redo $tmp/pyderasn-"$release"/doc/build.log
 tar xvfC doc/download/termcolor-1.1.0.tar.gz $tmp --include "*/termcolor.py"
 mv -v $tmp/termcolor-*/termcolor.py $tmp/pyderasn-"$release"
 
-pip_hash=$(pip hash dist/pyderasn-"$release".tar.gz | sed -n '$p')
-
 cd $tmp
 find . -type d -exec chmod 755 {} +
 find . -type f -exec chmod 644 {} +
 chmod 755 pyderasn-"$release"/pyderasn.py
 tar cvf pyderasn-"$release".tar --uid=0 --gid=0 --numeric-owner pyderasn-"$release"
 zstd -19 -v pyderasn-"$release".tar
-gpg --detach-sign --sign --local-user 04A933D1BA20327A pyderasn-"$release".tar.zst
-
 tarball=pyderasn-"$release".tar.zst
+gpg --armor --detach-sign --sign --local-user pyderasn@cypherpunks.ru $tarball
+meta4-create -fn "$tarball" -mtime "$tarball" -sig "$tarball".asc \
+    http://www.pyderasn.cypherpunks.ru/download/"$tarball" \
+    http://y.www.pyderasn.cypherpunks.ru/download/"$tarball" < "$tarball" > "$tarball".meta4
+
 size=$(( $(stat -f %z $tarball) / 1024 ))
-hash=$(gpg --print-md SHA256 < $tarball)
 release_date=$(date "+%Y-%m-%d")
 
 cat <<EOF
@@ -38,14 +38,12 @@ An entry for documentation:
    * - \`\`pyderasn\`\` :ref:\`$release <release$release>\`
      - $release_date
      - $size KiB
-     - \`link <download/pyderasn-${release}.tar.zst>\`__
-       \`sign <download/pyderasn-${release}.tar.zst.sig>\`__
-     - \`\`$hash\`\`
-
-pyderasn==$release $pip_hash
+     - \`meta4 <download/pyderasn-${release}.tar.zst.meta4>\`__
+       \`tar <download/pyderasn-${release}.tar.zst>\`__
+       \`sig <download/pyderasn-${release}.tar.zst.asc>\`__
 EOF
 
-mv $tmp/$tarball $tmp/"$tarball".sig $cur/doc/download
+mv $tmp/$tarball $tmp/"$tarball".asc $tmp/"$tarball".meta4 $cur/doc/download
 
 cat <<EOF
 Subject: PyDERASN $release release announcement
@@ -66,16 +64,11 @@ PyDERASN'es home page is: http://www.pyderasn.cypherpunks.ru/
 Source code and its signature for that version can be found here:
 
     http://www.pyderasn.cypherpunks.ru/download/pyderasn-${release}.tar.zst ($size KiB)
-    http://www.pyderasn.cypherpunks.ru/download/pyderasn-${release}.tar.zst.sig
+    http://www.pyderasn.cypherpunks.ru/download/pyderasn-${release}.tar.zst.asc
 
-SHA256 hash: $hash
 GPG key: 2ED6 C846 3051 02DF 5B4E  0383 04A9 33D1 BA20 327A
          PyDERASN releases <pyderasn at cypherpunks dot ru>
 
-pip'es requirements file:
-
-    pyderasn==$release $pip_hash
-
 Please send questions regarding the use of PyDERASN, bug reports and patches
 to mailing list: http://lists.cypherpunks.ru/pyderasn_002ddevel.html
 EOF
index 48f7556a0c142013b8b38f6fc6190cdf7a94feea..3498a0708ce19be9823b720ce10dadad5c2bcb77 100644 (file)
@@ -1,4 +1,4 @@
 attrs==19.3.0
 coverage==4.5.4
-hypothesis==3.57.0
+hypothesis==6.39.4
 python-dateutil==2.8.1
index 3eb10715ed1400a0bd3c55dccd71419a46e7c499..54242a3bd537fc9360217174cb79b9ccf832a73a 100755 (executable)
@@ -4,7 +4,7 @@
 # pylint: disable=line-too-long,superfluous-parens,protected-access,too-many-lines
 # pylint: disable=too-many-return-statements,too-many-branches,too-many-statements
 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
-# Copyright (C) 2017-2021 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2024 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
@@ -235,6 +235,7 @@ Currently available context options:
 * :ref:`bered <bered_ctx>`
 * :ref:`defines_by_path <defines_by_path_ctx>`
 * :ref:`evgen_mode_upto <evgen_mode_upto_ctx>`
+* :ref:`keep_memoryview <keep_memoryview_ctx>`
 
 .. _pprinting:
 
@@ -706,6 +707,15 @@ creates read-only memoryview on the file contents::
    page cache used for mmaps. It can take twice the necessary size in
    the memory: both in page cache and ZFS ARC.
 
+.. _keep_memoryview_ctx:
+
+That read-only memoryview could be safe to be used as a value inside
+decoded :py:class:`pyderasn.OctetString` and :py:class:`pyderasn.Any`
+objects. You can enable that by setting `"keep_memoryview": True` in
+:ref:`decode context <ctx>`. No OCTET STRING and ANY values will be
+copied to memory. Of course that works only in DER encoding, where the
+value is continuously encoded.
+
 CER encoding
 ____________
 
@@ -1186,7 +1196,7 @@ except ImportError:  # pragma: no cover
     tzUTC = "missing"
 
 
-__version__ = "9.1"
+__version__ = "9.3"
 
 __all__ = (
     "agg_octet_string",
@@ -3630,6 +3640,7 @@ class OctetString(Obj):
     tag_default = tag_encode(4)
     asn1_type_name = "OCTET STRING"
     evgen_mode_skip_value = True
+    memoryview_safe = True
 
     def __init__(
             self,
@@ -3726,6 +3737,10 @@ class OctetString(Obj):
         self._assert_ready()
         return bytes(self._value)
 
+    def memoryview(self):
+        self._assert_ready()
+        return memoryview(self._value)
+
     def __eq__(self, their):
         if their.__class__ == bytes:
             return self._value == their
@@ -3839,12 +3854,15 @@ class OctetString(Obj):
                     decode_path=decode_path,
                     offset=offset,
                 )
+            if evgen_mode and self.evgen_mode_skip_value:
+                value = None
+            elif self.memoryview_safe and ctx.get("keep_memoryview", False):
+                value = v
+            else:
+                value = v.tobytes()
             try:
                 obj = self.__class__(
-                    value=(
-                        None if (evgen_mode and self.evgen_mode_skip_value)
-                        else v.tobytes()
-                    ),
+                    value=value,
                     bounds=(self._bound_min, self._bound_max),
                     impl=self.tag,
                     expl=self._expl,
@@ -4694,6 +4712,7 @@ class CommonString(OctetString):
          - utf-16-be
     """
     __slots__ = ()
+    memoryview_safe = False
 
     def _value_sanitize(self, value):
         value_raw = None
@@ -4743,6 +4762,9 @@ class CommonString(OctetString):
             return self._value.decode(self.encoding)
         return str(self._value)
 
+    def memoryview(self):
+        raise ValueError("CommonString does not support .memoryview()")
+
     def __repr__(self):
         return pp_console_row(next(self.pps()))
 
@@ -5842,7 +5864,7 @@ class Any(Obj):
             value = self._value_sanitize(value)
             self._value = value
             if self._expl is None:
-                if value.__class__ == bytes:
+                if value.__class__ == bytes or value.__class__ == memoryview:
                     tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
                 else:
                     tag_class, tag_num = value.tag_order
@@ -5852,7 +5874,7 @@ class Any(Obj):
         self.defined = None
 
     def _value_sanitize(self, value):
-        if value.__class__ == bytes:
+        if value.__class__ == bytes or value.__class__ == memoryview:
             if len(value) == 0:
                 raise ValueError("%s value can not be empty" % self.__class__.__name__)
             return value
@@ -5903,13 +5925,13 @@ class Any(Obj):
         self.defined = state.defined
 
     def __eq__(self, their):
-        if their.__class__ == bytes:
-            if self._value.__class__ == bytes:
+        if their.__class__ == bytes or their.__class__ == memoryview:
+            if self._value.__class__ == bytes or their.__class__ == memoryview:
                 return self._value == their
             return self._value.encode() == their
         if issubclass(their.__class__, Any):
             if self.ready and their.ready:
-                return bytes(self) == bytes(their)
+                return self.memoryview() == their.memoryview()
             return self.ready == their.ready
         return False
 
@@ -5930,8 +5952,17 @@ class Any(Obj):
         value = self._value
         if value.__class__ == bytes:
             return value
+        if value.__class__ == memoryview:
+            return bytes(value)
         return self._value.encode()
 
+    def memoryview(self):
+        self._assert_ready()
+        value = self._value
+        if value.__class__ == memoryview:
+            return memoryview(value)
+        return memoryview(bytes(self))
+
     @property
     def tlen(self):
         return 0
@@ -5939,20 +5970,20 @@ class Any(Obj):
     def _encode(self):
         self._assert_ready()
         value = self._value
-        if value.__class__ == bytes:
-            return value
+        if value.__class__ == bytes or value.__class__ == memoryview:
+            return bytes(self)
         return value.encode()
 
     def _encode1st(self, state):
         self._assert_ready()
         value = self._value
-        if value.__class__ == bytes:
+        if value.__class__ == bytes or value.__class__ == memoryview:
             return len(value), state
         return value.encode1st(state)
 
     def _encode2nd(self, writer, state_iter):
         value = self._value
-        if value.__class__ == bytes:
+        if value.__class__ == bytes or value.__class__ == memoryview:
             write_full(writer, value)
         else:
             value.encode2nd(writer, state_iter)
@@ -5960,7 +5991,7 @@ class Any(Obj):
     def _encode_cer(self, writer):
         self._assert_ready()
         value = self._value
-        if value.__class__ == bytes:
+        if value.__class__ == bytes or value.__class__ == memoryview:
             write_full(writer, value)
         else:
             value.encode_cer(writer)
@@ -6027,8 +6058,14 @@ class Any(Obj):
             )
         tlvlen = tlen + llen + l
         v, tail = tlv[:tlvlen], v[l:]
+        if evgen_mode:
+            value = None
+        elif ctx.get("keep_memoryview", False):
+            value = v
+        else:
+            value = v.tobytes()
         obj = self.__class__(
-            value=None if evgen_mode else v.tobytes(),
+            value=value,
             expl=self._expl,
             optional=self.optional,
             _decoded=(offset, 0, tlvlen),
@@ -6043,7 +6080,7 @@ class Any(Obj):
         value = self._value
         if value is None:
             pass
-        elif value.__class__ == bytes:
+        elif value.__class__ == bytes or value.__class__ == memoryview:
             value = None
         else:
             value = repr(value)
@@ -6053,7 +6090,10 @@ class Any(Obj):
             obj_name=self.__class__.__name__,
             decode_path=decode_path,
             value=value,
-            blob=self._value if self._value.__class__ == bytes else None,
+            blob=self._value if (
+                self._value.__class__ == bytes or
+                value.__class__ == memoryview
+            ) else None,
             optional=self.optional,
             default=self == self.default,
             impl=None if self.tag == self.tag_default else tag_decode(self.tag),
index 1936b6ea2617f1a069ed4938feec33b7c12e0930..fb455803925ec43e01e8674b2ecde49862e42bd4 100644 (file)
@@ -1,6 +1,6 @@
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
-# Copyright (C) 2017-2021 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2024 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
index 9dc5c002d5112b37b91094d348795ce4d389ac53..9174e2fb994965d2400162227e7d953c245403be 100644 (file)
@@ -1,6 +1,6 @@
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
-# Copyright (C) 2017-2021 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2024 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
index 79b2f1daa24ae8e06437f173fdf214a254b165ac..e43b4c22fbd23390c83da7eaec791ea4fca461ff 100644 (file)
@@ -1,6 +1,6 @@
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
-# Copyright (C) 2017-2021 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2024 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
@@ -229,7 +229,7 @@ class TestGoSelfSignedVector(TestCase):
             "ba3ca12568fdc6c7b4511cd40a7f659980402df2b998bb9a4a8cbeb34c0f0a78c",
             "f8d91ede14a5ed76bf116fe360aafa8821490435",
         )))
-        crt = Certificate().decod(raw)
+        crt = Certificate().decod(raw, ctx={"keep_memoryview": True})
         tbs = crt["tbsCertificate"]
         self.assertEqual(tbs["version"], 0)
         self.assertFalse(tbs["version"].decoded)
@@ -301,6 +301,7 @@ class TestGoSelfSignedVector(TestCase):
             "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
         )))))
         self.assertSequenceEqual(crt.encode(), raw)
+        crt = Certificate().decod(raw)
         pprint(crt)
         repr(crt)
         pickle_loads(pickle_dumps(crt, pickle_proto))
index 4febf7400a328699bba1d8d3cc17da131109df8f..e8f8bdf4570e1c52adbf2b7a7c5a827c47a2099c 100644 (file)
@@ -1,6 +1,6 @@
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
-# Copyright (C) 2017-2021 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2024 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
@@ -679,7 +679,7 @@ class TestBoolean(CommonMixin, TestCase):
             repr(obj)
             list(obj.pps())
 
-    @given(integers(min_value=2))
+    @given(integers(min_value=2, max_value=10))
     def test_invalid_len(self, l):
         with self.assertRaises(InvalidLength):
             Boolean().decode(b"".join((
@@ -1272,6 +1272,8 @@ def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=
         if generation_choice == 2 or draw(booleans()):
             return draw(binary(max_size=len(schema) // 8))
         if generation_choice == 3 or draw(booleans()):
+            if len(schema) == 0:
+                return ()
             return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
         return None
     value = _value(value_required)
@@ -2214,8 +2216,18 @@ class TestOctetString(CommonMixin, TestCase):
         integers(min_value=0),
         binary(max_size=5),
         decode_path_strat,
+        booleans(),
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
+    def test_symmetric(
+            self,
+            values,
+            value,
+            tag_expl,
+            offset,
+            tail_junk,
+            decode_path,
+            keep_memoryview,
+    ):
         for klass in (OctetString, OctetStringInherited):
             _, _, _, _, default, optional, _decoded = values
             obj = klass(
@@ -2243,6 +2255,7 @@ class TestOctetString(CommonMixin, TestCase):
                 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
                 obj_expled_encoded,
             )
+            ctx_dummy["keep_memoryview"] = keep_memoryview
             ctx_copied = deepcopy(ctx_dummy)
             obj_decoded, tail = obj_expled.decode(
                 obj_expled_encoded + tail_junk,
@@ -2258,6 +2271,10 @@ class TestOctetString(CommonMixin, TestCase):
             self.assertNotEqual(obj_decoded, obj)
             self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
             self.assertEqual(bytes(obj_decoded), bytes(obj))
+            self.assertIsInstance(
+                obj_decoded._value,
+                memoryview if keep_memoryview else bytes,
+            )
             self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
             self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
             self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
@@ -2678,8 +2695,8 @@ def oid_strategy(draw):
     if first_arc in (0, 1):
         second_arc = draw(integers(min_value=0, max_value=39))
     else:
-        second_arc = draw(integers(min_value=0))
-    other_arcs = draw(lists(integers(min_value=0)))
+        second_arc = draw(integers(min_value=0, max_value=1 << 63))
+    other_arcs = draw(lists(integers(min_value=0, max_value=1 << 63)))
     return tuple([first_arc, second_arc] + other_arcs)
 
 
@@ -2910,21 +2927,27 @@ class TestObjectIdentifier(CommonMixin, TestCase):
         with self.assertRaisesRegex(DecodeError, "unfinished OID"):
             obj.decode(data)
 
-    @given(integers(min_value=0))
+    @given(integers(min_value=0, max_value=1 << 63))
     def test_invalid_short(self, value):
         with self.assertRaises(InvalidOID):
             ObjectIdentifier((value,))
         with self.assertRaises(InvalidOID):
             ObjectIdentifier("%d" % value)
 
-    @given(integers(min_value=3), integers(min_value=0))
+    @given(
+        integers(min_value=3, max_value=1 << 63),
+        integers(min_value=0, max_value=1 << 63),
+    )
     def test_invalid_first_arc(self, first_arc, second_arc):
         with self.assertRaises(InvalidOID):
             ObjectIdentifier((first_arc, second_arc))
         with self.assertRaises(InvalidOID):
             ObjectIdentifier("%d.%d" % (first_arc, second_arc))
 
-    @given(integers(min_value=0, max_value=1), integers(min_value=40))
+    @given(
+        integers(min_value=0, max_value=1),
+        integers(min_value=40, max_value=1 << 63),
+    )
     def test_invalid_second_arc(self, first_arc, second_arc):
         with self.assertRaises(InvalidOID):
             ObjectIdentifier((first_arc, second_arc))
@@ -5259,8 +5282,18 @@ class TestAny(CommonMixin, TestCase):
         integers(min_value=0),
         binary(max_size=5),
         decode_path_strat,
+        booleans(),
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
+    def test_symmetric(
+            self,
+            values,
+            value,
+            tag_expl,
+            offset,
+            tail_junk,
+            decode_path,
+            keep_memoryview,
+    ):
         for klass in (Any, AnyInherited):
             _, _, optional, _decoded = values
             obj = klass(value=value, optional=optional, _decoded=_decoded)
@@ -5280,6 +5313,7 @@ class TestAny(CommonMixin, TestCase):
             list(obj_expled.pps())
             pprint(obj_expled, big_blobs=True, with_decode_path=True)
             obj_expled_encoded = obj_expled.encode()
+            ctx_dummy["keep_memoryview"] = keep_memoryview
             ctx_copied = deepcopy(ctx_dummy)
             obj_decoded, tail = obj_expled.decode(
                 obj_expled_encoded + tail_junk,
@@ -5294,6 +5328,10 @@ class TestAny(CommonMixin, TestCase):
             self.assertEqual(obj_decoded, obj_expled)
             self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
             self.assertEqual(bytes(obj_decoded), bytes(obj))
+            self.assertIsInstance(
+                obj_decoded._value,
+                memoryview if keep_memoryview else bytes,
+            )
             self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
             self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
             self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
@@ -6723,7 +6761,7 @@ class SeqOfMixin(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(False)] * d.draw(integers(max_value=bound_min - 1))
+        value = [Boolean(False)] * d.draw(integers(min_value=0, max_value=bound_min - 1))
         with self.assertRaises(BoundsError) as err:
             SeqOf(value=value, bounds=(bound_min, bound_max))
         repr(err.exception)
@@ -7428,7 +7466,11 @@ class TestPP(TestCase):
     def test_oid_printing(self, d):
         oids = {
             str(ObjectIdentifier(k)): v * 2
-            for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
+            for k, v in d.draw(dictionaries(
+                oid_strategy(),
+                text_letters(),
+                min_size=1,
+            )).items()
         }
         chosen = d.draw(sampled_from(sorted(oids)))
         chosen_id = oids[chosen]