From 079b95a6c3933a37516187a17a6ef971fcdca17b Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Tue, 18 Feb 2020 10:04:48 +0300 Subject: [PATCH] Strict DEFAULT check in evgen mode --- VERSION | 2 +- doc/install.rst | 12 ++++----- doc/news.rst | 10 ++++++++ pyderasn.py | 55 +++++++++++++++++++++++++----------------- tests/test_pyderasn.py | 36 ++++++++++++++++++++++++--- 5 files changed, 82 insertions(+), 33 deletions(-) diff --git a/VERSION b/VERSION index 5904f7a..f994162 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.2 +7.3 diff --git a/doc/install.rst b/doc/install.rst index e57faad..3d380ea 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -4,11 +4,11 @@ Install Preferable way is to :ref:`download ` tarball with the signature from `official website `__:: - $ [fetch|wget] http://pyderasn.cypherpunks.ru/pyderasn-7.2.tar.xz - $ [fetch|wget] http://pyderasn.cypherpunks.ru/pyderasn-7.2.tar.xz.sig - $ gpg --verify pyderasn-7.2.tar.xz.sig pyderasn-7.2.tar.xz - $ xz --decompress --stdout pyderasn-7.2.tar.xz | tar xf - - $ cd pyderasn-7.2 + $ [fetch|wget] http://pyderasn.cypherpunks.ru/pyderasn-7.3.tar.xz + $ [fetch|wget] http://pyderasn.cypherpunks.ru/pyderasn-7.3.tar.xz.sig + $ gpg --verify pyderasn-7.3.tar.xz.sig pyderasn-7.3.tar.xz + $ xz --decompress --stdout pyderasn-7.3.tar.xz | tar xf - + $ cd pyderasn-7.3 $ python setup.py install # or copy pyderasn.py (+six.py, possibly termcolor.py) to your PYTHONPATH @@ -19,7 +19,7 @@ You can also find it mirrored on :ref:`download ` page. You could use pip (**no** OpenPGP authentication is performed!) with PyPI:: $ cat > requirements.txt <` option. - .. warning:: - - Check for default value existence is not performed in - ``evgen_mode``, because previously decoded values are not stored - in memory, to be able to compare them. + All values with DEFAULT specified are decoded atomically in + :ref:`evgen mode `. If DEFAULT value is some kind of + SEQUENCE, then it will be yielded as a single element, not + disassembled. That is required for DEFAULT existence check. Two sequences are equal if they have equal specification (schema), implicit/explicit tagging and the same values. @@ -6425,9 +6429,10 @@ class Sequence(SequenceEncode1stMixing, Obj): len(v) == 0 ): continue + spec_defaulted = spec.default is not None sub_decode_path = decode_path + (name,) try: - if evgen_mode: + if evgen_mode and not spec_defaulted: for _decode_path, value, v_tail in spec.decode_evgen( v, sub_offset, @@ -6505,9 +6510,10 @@ class Sequence(SequenceEncode1stMixing, Obj): vlen += value_len sub_offset += value_len v = v_tail - if not evgen_mode: - if spec.default is not None and value == spec.default: - # This will not work in evgen_mode + if spec_defaulted: + if evgen_mode: + yield sub_decode_path, value, v_tail + if value == spec.default: if ctx_bered or ctx_allow_default_values: ber_encoded = True else: @@ -6517,6 +6523,7 @@ class Sequence(SequenceEncode1stMixing, Obj): decode_path=sub_decode_path, offset=sub_offset, ) + if not evgen_mode: values[name] = value spec_defines = getattr(spec, "defines", ()) if len(spec_defines) == 0: @@ -6716,7 +6723,8 @@ class Set(Sequence, SequenceEncode1stMixing): decode_path=decode_path, offset=offset, ) - if evgen_mode: + spec_defaulted = spec.default is not None + if evgen_mode and not spec_defaulted: for _decode_path, value, v_tail in spec.decode_evgen( v, sub_offset, @@ -6748,17 +6756,20 @@ class Set(Sequence, SequenceEncode1stMixing): decode_path=sub_decode_path, offset=sub_offset, ) - if spec.default is None or value != spec.default: - pass - elif ctx_bered or ctx_allow_default_values: - ber_encoded = True - else: - raise DecodeError( - "DEFAULT value met", - klass=self.__class__, - decode_path=sub_decode_path, - offset=sub_offset, - ) + if spec_defaulted: + if evgen_mode: + yield sub_decode_path, value, v_tail + if value != spec.default: + pass + elif ctx_bered or ctx_allow_default_values: + ber_encoded = True + else: + raise DecodeError( + "DEFAULT value met", + klass=self.__class__, + decode_path=sub_decode_path, + offset=sub_offset, + ) values[name] = value del _specs_items[name] tag_order_prev = value_tag_order diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index 46e10e5..b16c6f6 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -6274,25 +6274,34 @@ class SeqMixing(object): min_size=len(_schema), max_size=len(_schema), ))] + class Wahl(Choice): + schema = (("int", Integer()),) class SeqWithoutDefault(self.base_klass): schema = [ - (n, Integer(impl=t)) + (n, Wahl(expl=t)) for (n, _), t in zip(_schema, tags) ] seq_without_default = SeqWithoutDefault() for name, value in _schema: - seq_without_default[name] = Integer(value) + seq_without_default[name] = Wahl(("int", Integer(value))) seq_encoded = seq_without_default.encode() + seq_without_default.decode(seq_encoded) + self.assertEqual( + len(list(seq_without_default.decode_evgen(seq_encoded))), + len(_schema) * 2 + 1, + ) class SeqWithDefault(self.base_klass): schema = [ - (n, Integer(default=v, impl=t)) + (n, Wahl(default=Wahl(("int", Integer(v))), expl=t)) for (n, v), t in zip(_schema, tags) ] seq_with_default = SeqWithDefault() with assertRaisesRegex(self, DecodeError, "DEFAULT value met"): seq_with_default.decode(seq_encoded) + with assertRaisesRegex(self, DecodeError, "DEFAULT value met"): + list(seq_with_default.decode_evgen(seq_encoded)) for ctx in ({"bered": True}, {"allow_default_values": True}): seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx) self.assertTrue(seq_decoded.ber_encoded) @@ -6302,7 +6311,21 @@ class SeqMixing(object): self.assertTrue(seq_decoded.bered) for name, value in _schema: self.assertEqual(seq_decoded[name], seq_with_default[name]) - self.assertEqual(seq_decoded[name], value) + self.assertEqual(seq_decoded[name].value, value) + self.assertEqual( + len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))), + len(_schema) + 1, + ) + + seq_without_default = SeqWithoutDefault() + for name, value in _schema: + seq_without_default[name] = Wahl(("int", Integer(value + 1))) + seq_encoded = seq_without_default.encode() + seq_with_default.decode(seq_encoded) + self.assertEqual( + len(list(seq_with_default.decode_evgen(seq_encoded))), + len(_schema) + 1, + ) @given(data_strategy()) def test_missing_from_spec(self, d): @@ -6327,6 +6350,8 @@ class SeqMixing(object): seq_missing = SeqMissing() with self.assertRaises(TagMismatch): seq_missing.decode(seq_encoded) + with self.assertRaises(TagMismatch): + list(seq_missing.decode_evgen(seq_encoded)) def test_bered(self): class Seq(self.base_klass): @@ -6353,6 +6378,9 @@ class SeqMixing(object): encoded = Seq.tag_default + len_encode(len(encoded)) + encoded with self.assertRaises(DecodeError): Seq().decode(encoded) + with self.assertRaises(DecodeError): + list(Seq().decode_evgen(encoded)) + list(Seq().decode_evgen(encoded, ctx={"bered": True})) decoded, _ = Seq().decode(encoded, ctx={"bered": True}) self.assertFalse(decoded.ber_encoded) self.assertFalse(decoded.lenindef) -- 2.44.0