• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding: utf-8
2from __future__ import unicode_literals, division, absolute_import, print_function
3
4import unittest
5
6from asn1crypto import parser
7
8from ._unittest_compat import patch
9
10patch()
11
12
13class ParserTests(unittest.TestCase):
14
15    def test_parser(self):
16        result = parser.parse(b'\x02\x01\x00')
17        self.assertIsInstance(result, tuple)
18        self.assertEqual(0, result[0])
19        self.assertEqual(0, result[1])
20        self.assertEqual(2, result[2])
21        self.assertEqual(b'\x02\x01', result[3])
22        self.assertEqual(b'\x00', result[4])
23        self.assertEqual(b'', result[5])
24
25    def test_peek(self):
26        self.assertEqual(3, parser.peek(b'\x02\x01\x00\x00'))
27
28    def test_parse_indef_nested(self):
29        data = b'\x24\x80\x24\x80\x24\x80\x04\x00\x00\x00\x00\x00\x00\x00'
30        result = parser.parse(data)
31        self.assertEqual(b'\x24\x80', result[3])
32        self.assertEqual(b'\x24\x80\x24\x80\x04\x00\x00\x00\x00\x00', result[4])
33        self.assertEqual(b'\x00\x00', result[5])
34
35    def test_parser_strict(self):
36        with self.assertRaises(ValueError):
37            parser.parse(b'\x02\x01\x00\x00', strict=True)
38
39    def test_emit(self):
40        self.assertEqual(b'\x02\x01\x00', parser.emit(0, 0, 2, b'\x00'))
41
42    def test_emit_type_errors(self):
43        with self.assertRaises(TypeError):
44            parser.emit('0', 0, 2, b'\x00')
45
46        with self.assertRaises(ValueError):
47            parser.emit(-1, 0, 2, b'\x00')
48
49        with self.assertRaises(TypeError):
50            parser.emit(0, '0', 2, b'\x00')
51
52        with self.assertRaises(ValueError):
53            parser.emit(0, 5, 2, b'\x00')
54
55        with self.assertRaises(TypeError):
56            parser.emit(0, 0, '2', b'\x00')
57
58        with self.assertRaises(ValueError):
59            parser.emit(0, 0, -1, b'\x00')
60
61        with self.assertRaises(TypeError):
62            parser.emit(0, 0, 2, '\x00')
63
64    def test_parser_large_tag(self):
65        # One extra byte
66        result = parser.parse(b'\x7f\x49\x00')
67        self.assertEqual(1, result[0])
68        self.assertEqual(1, result[1])
69        self.assertEqual(73, result[2])
70        self.assertEqual(b'\x7f\x49\x00', result[3])
71        self.assertEqual(b'', result[4])
72        self.assertEqual(b'', result[5])
73
74        # Two extra bytes
75        result = parser.parse(b'\x7f\x81\x49\x00')
76        self.assertEqual(1, result[0])
77        self.assertEqual(1, result[1])
78        self.assertEqual(201, result[2])
79        self.assertEqual(b'\x7f\x81\x49\x00', result[3])
80        self.assertEqual(b'', result[4])
81        self.assertEqual(b'', result[5])
82
83        # Three extra bytes
84        result = parser.parse(b'\x7f\x81\x80\x00\x00')
85        self.assertEqual(1, result[0])
86        self.assertEqual(1, result[1])
87        self.assertEqual(16384, result[2])
88        self.assertEqual(b'\x7f\x81\x80\x00\x00', result[3])
89        self.assertEqual(b'', result[4])
90        self.assertEqual(b'', result[5])
91
92    def test_parser_insufficient_data(self):
93        # No tag
94        with self.assertRaises(ValueError):
95            parser.parse(b'')
96
97        # Long-form tag is truncated
98        with self.assertRaises(ValueError):
99            parser.parse(b'\xbf')
100        with self.assertRaises(ValueError):
101            parser.parse(b'\xbf\x81')
102
103        # No length
104        with self.assertRaises(ValueError):
105            parser.parse(b'\x04')
106        with self.assertRaises(ValueError):
107            parser.parse(b'\xbf\x1f')
108
109        # Long-form length is truncated
110        with self.assertRaises(ValueError):
111            parser.parse(b'\x04\x81')
112        with self.assertRaises(ValueError):
113            parser.parse(b'\x04\x82\x01')
114
115        # Contents are truncated
116        with self.assertRaises(ValueError):
117            parser.parse(b'\x04\x02\x00')
118        with self.assertRaises(ValueError):
119            parser.parse(b'\x04\x81\x80' + (b'\x00' * 127))
120
121    def test_parser_bounded_recursion(self):
122        with self.assertRaises(ValueError):
123            parser.parse(b'\x30\x80' * 1000)
124
125    def test_parser_indef_missing_eoc(self):
126        with self.assertRaises(ValueError):
127            parser.parse(b'\x30\x80')
128        with self.assertRaises(ValueError):
129            parser.parse(b'\x30\x80\x30\x80\x00\x00')
130
131    def test_parser_indef_long_zero_length(self):
132        # The parser should not confuse the long-form zero length for an EOC.
133        result = parser.parse(b'\x30\x80\x30\x82\x00\x00\x00\x00')
134        self.assertIsInstance(result, tuple)
135        self.assertEqual(0, result[0])
136        self.assertEqual(1, result[1])
137        self.assertEqual(16, result[2])
138        self.assertEqual(b'\x30\x80', result[3])
139        self.assertEqual(b'\x30\x82\x00\x00', result[4])
140        self.assertEqual(b'\x00\x00', result[5])
141
142    def test_parser_indef_primitive(self):
143        with self.assertRaises(ValueError):
144            parser.parse(b'\x04\x80\x00\x00')
145
146    def test_parse_nonminimal_tag(self):
147        with self.assertRaises(ValueError):
148            # Should be b'\x04\x00'
149            parser.parse(b'\x1f\x04\x00')
150
151        with self.assertRaises(ValueError):
152            # Should be b'\xbf\x1f\x00'
153            parser.parse(b'\xbf\x80\x1f\x00')
154