From: Sergey Matveev Date: Sun, 16 Feb 2020 17:38:08 +0000 (+0300) Subject: Store OIDs as an array.array X-Git-Tag: 7.0~1 X-Git-Url: http://www.git.cypherpunks.ru/?p=pyderasn.git;a=commitdiff_plain;h=749705c0df79a03dfda53dc0f78044efba8590a6 Store OIDs as an array.array --- diff --git a/doc/news.rst b/doc/news.rst index 6266bc0..cdc961d 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -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 diff --git a/pyderasn.py b/pyderasn.py index 68dd213..7bb1799 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -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, diff --git a/tests/test_compli.py b/tests/test_compli.py index 8e0ff82..9996d84 100644 --- a/tests/test_compli.py +++ b/tests/test_compli.py @@ -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)