pyderasn.py | 8 ++++++++ tests/test_pyderasn.py | 44 +++++++++++++++++++++++++++++++++++++++----- diff --git a/pyderasn.py b/pyderasn.py index 9e04dc67a7b94aaf1ea9b076877d13f024150a7d8e262019bf2235d543ae99ce..d676ebc26a7aff9986df175ed5c3e9664813fb5e4586f20474aafee7fd31a4ef 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -542,6 +542,7 @@ from collections import OrderedDict from datetime import datetime from math import ceil from os import environ +from string import ascii_letters from string import digits from six import add_metaclass @@ -3511,6 +3512,13 @@ __slots__ = () tag_default = tag_encode(19) encoding = "ascii" asn1_type_name = "PrintableString" + allowable_chars = set((ascii_letters + digits + " '()+,-./:=?").encode("ascii")) + + def _value_sanitize(self, value): + value = super(PrintableString, self)._value_sanitize(value) + if not set(value) <= self.allowable_chars: + raise DecodeError("non-printable value") + return value class TeletexString(CommonString): diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index 6f023d05f607b10f44dc2f86cfc05a6b52fb1013d40e3ae1a22b8b6e7e9d458d..43ed60780cb7ab4e2f28db1d9f1c8bd5dfdec0c93577fc805c79c00edda43130 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -3281,12 +3281,15 @@ class TestUTF8String(StringMixin, CommonMixin, TestCase): base_klass = UTF8String +cyrillic_letters = text( + alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))), + min_size=1, + max_size=5, +) + + class UnicodeDecodeErrorMixin(object): - @given(text( - alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))), - min_size=1, - max_size=5, - )) + @given(cyrillic_letters) def test_unicode_decode_error(self, cyrillic_text): with self.assertRaises(DecodeError): self.base_klass(cyrillic_text) @@ -3331,6 +3334,34 @@ CommonMixin, TestCase, ): base_klass = PrintableString + + def text_alphabet(self): + return ascii_letters + digits + " '()+,-./:=?" + + @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5)) + def test_non_printable(self, non_printable_text): + with assertRaisesRegex(self, DecodeError, "non-printable"): + self.base_klass(non_printable_text) + + @given( + sets(integers(min_value=0, max_value=10), min_size=2, max_size=2), + integers(min_value=0), + decode_path_strat, + ) + def test_invalid_bounds_while_decoding(self, ints, offset, decode_path): + value, bound_min = list(sorted(ints)) + + class String(self.base_klass): + bounds = (bound_min, bound_min) + with self.assertRaises(DecodeError) as err: + String().decode( + self.base_klass(b"1" * value).encode(), + offset=offset, + decode_path=decode_path, + ) + repr(err.exception) + self.assertEqual(err.exception.offset, offset) + self.assertEqual(err.exception.decode_path, decode_path) class TestTeletexString( @@ -5837,8 +5868,11 @@ ) seq = Seq() seq["erste"] = PrintableString("test") self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374")) + # Asterisk is actually not allowable + PrintableString.allowable_chars |= set(b"*") seq["erste"] = PrintableString("test*") self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a")) + PrintableString.allowable_chars -= set(b"*") class Seq(Sequence): schema = (