]> Cypherpunks.ru repositories - pyderasn.git/commitdiff
Store OIDs as an array.array
authorSergey Matveev <stargrave@stargrave.org>
Sun, 16 Feb 2020 17:38:08 +0000 (20:38 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 16 Feb 2020 18:25:49 +0000 (21:25 +0300)
doc/news.rst
pyderasn.py
tests/test_compli.py

index 6266bc0fd40f55df9550a384044035cbe845094a..cdc961d1a85b553876b8632112541b93a801933c 100644 (file)
@@ -16,6 +16,9 @@ News
 * ``Any`` allows an ordinary ``Obj`` storing, without its forceful
   encoded representation storage. That is required for CER encoding
   mode, where we do not know in advance what encoding will be used
+* ``ObjectIdentifier`` stores values as C unsigned long integer,
+  forbidding storage of huge integers, that must not be a problem in
+  practice
 * Initial support for so called ``evgen_mode``: event generation mode,
   where no in-memory objects storing happens, giving ability to process
   ASN.1 data without fully parsing it first. ``python -m pyderasn`` has
index 68dd21339f62e6801e88788215eb19fcda613fb7..7bb1799863c454bb22bdbdc70c75411c47635f04 100755 (executable)
@@ -1084,6 +1084,7 @@ Now you can print only the specified tree, for example signature algorithm::
                          . . 05:00
 """
 
+from array import array
 from codecs import getdecoder
 from codecs import getencoder
 from collections import namedtuple
@@ -4130,7 +4131,7 @@ class ObjectIdentifier(Obj):
 
     def __add__(self, their):
         if their.__class__ == tuple:
-            return self.__class__(self._value + their)
+            return self.__class__(self._value + array("L", their))
         if isinstance(their, self.__class__):
             return self.__class__(self._value + their._value)
         raise InvalidValueType((self.__class__, tuple))
@@ -4140,10 +4141,15 @@ class ObjectIdentifier(Obj):
             return value._value
         if isinstance(value, string_types):
             try:
-                value = tuple(pureint(arc) for arc in value.split("."))
+                value = array("L", (pureint(arc) for arc in value.split(".")))
             except ValueError:
                 raise InvalidOID("unacceptable arcs values")
         if value.__class__ == tuple:
+            try:
+                value = array("L", value)
+            except OverflowError as err:
+                raise InvalidOID(repr(err))
+        if value.__class__ is array:
             if len(value) < 2:
                 raise InvalidOID("less than 2 arcs")
             first_arc = value[0]
@@ -4203,7 +4209,7 @@ class ObjectIdentifier(Obj):
 
     def __eq__(self, their):
         if their.__class__ == tuple:
-            return self._value == their
+            return self._value == array("L", their)
         if not issubclass(their.__class__, ObjectIdentifier):
             return False
         return (
@@ -4295,7 +4301,7 @@ class ObjectIdentifier(Obj):
                 offset=offset,
             )
         v, tail = v[:l], v[l:]
-        arcs = []
+        arcs = array("L")
         ber_encoded = False
         while len(v) > 0:
             i = 0
@@ -4306,10 +4312,23 @@ class ObjectIdentifier(Obj):
                     if ctx.get("bered", False):
                         ber_encoded = True
                     else:
-                        raise DecodeError("non normalized arc encoding")
+                        raise DecodeError(
+                            "non normalized arc encoding",
+                            klass=self.__class__,
+                            decode_path=decode_path,
+                            offset=offset,
+                        )
                 arc = (arc << 7) | (octet & 0x7F)
                 if octet & 0x80 == 0:
-                    arcs.append(arc)
+                    try:
+                        arcs.append(arc)
+                    except OverflowError:
+                        raise DecodeError(
+                            "too huge value for local unsigned long",
+                            klass=self.__class__,
+                            decode_path=decode_path,
+                            offset=offset,
+                        )
                     v = v[i + 1:]
                     break
                 i += 1
@@ -4331,7 +4350,7 @@ class ObjectIdentifier(Obj):
             first_arc = 2
             second_arc -= 80
         obj = self.__class__(
-            value=tuple([first_arc, second_arc] + arcs[1:]),
+            value=array("L", (first_arc, second_arc)) + arcs[1:],
             impl=self.tag,
             expl=self._expl,
             default=self.default,
index 8e0ff827480ca6e68404eb0f1f903f03f8b442e8..9996d84a1472137c1ab9e15e331a3f0dfc32535b 100644 (file)
@@ -139,7 +139,8 @@ class TestTestSuite(TestCase):
 
     def test_tc22(self):
         data = load_tc(22)
-        ObjectIdentifier().decode(data)
+        with assertRaisesRegex(self, DecodeError, "too huge value"):
+            ObjectIdentifier().decode(data)
 
     def test_tc23(self):
         data = load_tc(23)