From 73db29cf680d46539f651e742acd1942414ce9a1 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 15 Aug 2018 23:02:16 +0300 Subject: [PATCH] Check that explicit tag is not out-of-bounds --- VERSION | 2 +- doc/news.rst | 9 +++++++++ pyderasn.py | 34 +++++++++++++++++++++++++++++++++- tests/test_pyderasn.py | 10 ++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 24ee5b1..6324d40 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.13 +3.14 diff --git a/doc/news.rst b/doc/news.rst index 6e2427c..81db4f5 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -1,6 +1,15 @@ News ==== +.. _release3.14: + +3.14 +---- +* Additional encoding validness check: explicit tag must contain exactly + one object inside. Throw DecodeError otherwise +* ``allow_expl_oob`` context and command-line options allow skipping of + that check + .. _release3.13: 3.13 diff --git a/pyderasn.py b/pyderasn.py index 92ffc17..6db8017 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -213,6 +213,7 @@ decoding process. Currently available context options: +* :ref:`allow_expl_oob ` * :ref:`bered ` * :ref:`defines_by_path ` * :ref:`strict_default_existence ` @@ -393,6 +394,22 @@ constructed primitive types should be parsed successfully. EOC (end-of-contents) token's length is taken in advance in object's value length. +.. _allow_expl_oob_ctx: + +Allow explicit tag out-of-bound +------------------------------- + +Invalid BER encoding could contain ``EXPLICIT`` tag containing more than +one value, more than one object. If you set ``allow_expl_oob`` context +option to True, then no error will be raised and that invalid encoding +will be silently further processed. But pay attention that offsets and +lengths will be invalid in that case. + +.. warning:: + + This option should be used only for skipping some decode errors, just + to see the decoded structure somehow. + Primitive types --------------- @@ -1092,6 +1109,13 @@ class Obj(object): if tag_only: return obj, tail = result + if obj.tlvlen < l and not ctx.get("allow_expl_oob", False): + raise DecodeError( + "explicit tag out-of-bound, longer than data", + klass=self.__class__, + decode_path=decode_path, + offset=offset, + ) return obj, (tail if leavemm else tail.tobytes()) @property @@ -5246,6 +5270,11 @@ def main(): # pragma: no cover "--decode-path-only", help="Print only specified decode path", ) + parser.add_argument( + "--allow-expl-oob", + action="store_true", + help="Allow explicit tag out-of-bound", + ) parser.add_argument( "DERFile", type=argparse.FileType("rb"), @@ -5262,7 +5291,10 @@ def main(): # pragma: no cover pprinter = partial(pprint, big_blobs=True) else: schema, pprinter = generic_decoder() - ctx = {"bered": not args.nobered} + ctx = { + "bered": not args.nobered, + "allow_expl_oob": args.allow_expl_oob, + } if args.defines_by_path is not None: ctx["defines_by_path"] = obj_by_path(args.defines_by_path) obj, tail = schema().decode(der, ctx=ctx) diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index c85a90a..adad7e9 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -5922,3 +5922,13 @@ class TestX690PrefixedType(TestCase): VisibleString("Jones", impl=tag_ctxp(2)).encode(), hexdec("82054A6F6E6573"), ) + + +class TestExplOOB(TestCase): + def runTest(self): + expl = tag_ctxc(123) + raw = Integer(123).encode() + Integer(234).encode() + raw = b"".join((expl, len_encode(len(raw)), raw)) + with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"): + Integer(expl=expl).decode(raw) + Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True}) -- 2.44.0