doc/news.rst | 3 +++ pyderasn.py | 33 ++++++++++++++++++++++++++------- tests/test_compli.py | 3 ++- diff --git a/doc/news.rst b/doc/news.rst index 39ae9df0ff85020a6b880d86dacbff42d135128df7fc2bfd09e3dc8e992d965e..14296d8c654194875dc9ac6acac333e3e916d5f51efe3eb93a122b7272d60091 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -16,6 +16,9 @@ bounds are greater than zero * ``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 eb75909c90d0b982409a67c5763cff34d37f24af048db98c911f24415079f265..dbfc2e8fe33f9b60432465af7b00123cb6f24199bd8cf675ec2407727da76a33 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -1084,6 +1084,7 @@ 31 [0,0, 2] . parameters: [UNIV 5] ANY OPTIONAL . . 05:00 """ +from array import array from codecs import getdecoder from codecs import getencoder from collections import namedtuple @@ -4130,7 +4131,7 @@ self.defines = defines 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 @@ if issubclass(value.__class__, ObjectIdentifier): 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 @@ ) 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 @@ decode_path=decode_path, 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 @@ if i == 0 and octet == 0x80: 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 @@ else: 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 7aa897da76778c468a1e6c1a54d41689c2426a4ffa8d3a11ffe5c7592cd7e621..e9ae8755647d839ab6b29e5060c48e50afbd64270e276b848deac38394afb72b 100644 --- a/tests/test_compli.py +++ b/tests/test_compli.py @@ -139,7 +139,8 @@ ObjectIdentifier().decode(data, ctx={"bered": True}) 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)