]> Cypherpunks.ru repositories - pyderasn.git/commitdiff
Strict PrintableString sanitizing
authorElena Balakhonova <balakhonova@rnd.stcnet.ru>
Fri, 5 Oct 2018 15:11:39 +0000 (18:11 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Fri, 5 Oct 2018 15:35:52 +0000 (18:35 +0300)
X.680 41.4 table 10.

pyderasn.py
tests/test_pyderasn.py

index 1690ab087e8be7d2c69ccb22756fd42d584b1022..9a8ccddfa319df841e98a94ac4950f9b6f308c3d 100755 (executable)
@@ -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 @@ class PrintableString(CommonString):
     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):
index 6ea1d40a703e66003648a23f149a4195b9d53e44..8f02a02ad0fddaff99d2509bea8e726eebf1606d 100644 (file)
@@ -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)
@@ -3332,6 +3335,34 @@ class TestPrintableString(
 ):
     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(
         UnicodeDecodeErrorMixin,
@@ -5837,8 +5868,11 @@ class TestGoMarshalVectors(TestCase):
         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 = (