Skip to content

Commit

Permalink
Fix PER bound SEQUENCE OF encoding and decoding.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Dec 5, 2018
1 parent f0f531b commit d84f91a
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 12 deletions.
14 changes: 8 additions & 6 deletions asn1tools/codecs/per.py
Expand Up @@ -909,8 +909,10 @@ def encode(self, data, encoder):
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_non_negative_binary_integer(len(data) - self.minimum,
self.number_of_bits)
encoder.append_constrained_whole_number(len(data),
self.minimum,
self.maximum,
self.number_of_bits)

for entry in data:
self.element_type.encode(entry, encoder)
Expand All @@ -936,13 +938,13 @@ def decode(self, decoder):
pass
elif self.number_of_bits is None:
return self.decode_unbound(decoder)
elif self.minimum != self.maximum:
length = decoder.read_constrained_whole_number(self.minimum,
self.maximum,
self.number_of_bits)
else:
length = self.minimum

if self.minimum != self.maximum:
length += decoder.read_non_negative_binary_integer(
self.number_of_bits)

decoded = []

for _ in range(length):
Expand Down
89 changes: 85 additions & 4 deletions asn1tools/codecs/uper.py
Expand Up @@ -2,8 +2,6 @@
"""

from datetime import date

from . import DecodeError
from . import per
from . import restricted_utc_time_to_datetime
Expand All @@ -20,8 +18,6 @@
from .per import ObjectIdentifier
from .per import Sequence
from .per import Set
from .per import SequenceOf
from .per import SetOf
from .per import Choice
from .per import UTF8String
from .per import GeneralString
Expand Down Expand Up @@ -113,6 +109,59 @@ def decode(self, decoder):
return bytearray(data).decode('ascii')


class ArrayType(per.ArrayType):

def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= len(data) <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.append_length_determinant(len(data))

for entry in data:
self.element_type.encode(entry, encoder)

return

if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_non_negative_binary_integer(len(data) - self.minimum,
self.number_of_bits)

for entry in data:
self.element_type.encode(entry, encoder)

def decode(self, decoder):
length = None

if self.has_extension_marker:
bit = decoder.read_bit()

if bit:
length = decoder.read_length_determinant()

if length is not None:
pass
elif self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
length = self.minimum

if self.minimum != self.maximum:
length += decoder.read_non_negative_binary_integer(
self.number_of_bits)

decoded = []

for _ in range(length):
decoded_element = self.element_type.decode(decoder)
decoded.append(decoded_element)

return decoded


class Integer(Type):

def __init__(self, name):
Expand Down Expand Up @@ -239,6 +288,38 @@ def decode(self, decoder):
return decoder.read_bytes(length)


class SequenceOf(ArrayType):

def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker):
super(SequenceOf, self).__init__(name,
element_type,
minimum,
maximum,
has_extension_marker,
'SEQUENCE OF')


class SetOf(ArrayType):

def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker):
super(SetOf, self).__init__(name,
element_type,
minimum,
maximum,
has_extension_marker,
'SET OF')


class NumericString(KnownMultiplierStringType):

ALPHABET = bytearray(NUMERIC_STRING.encode('ascii'))
Expand Down
4 changes: 3 additions & 1 deletion tests/test_per.py
Expand Up @@ -681,6 +681,7 @@ def test_sequence_of(self):
"} "
"G ::= SEQUENCE SIZE (1..2, ..., 6..7) OF INTEGER "
"H ::= SEQUENCE SIZE (1..MAX) OF INTEGER "
"I ::= SEQUENCE SIZE (1..10000) OF OCTET STRING "
"END",
'per')

Expand Down Expand Up @@ -709,7 +710,8 @@ def test_sequence_of(self):
('G',
6 * [1],
b'\x80\x06\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'),
('H', [1], b'\x01\x01\x01')
('H', [1], b'\x01\x01\x01'),
('I', 300 * [b'\x56'], b'\x01\x2b' + 300 * b'\x01\x56')
]

for type_name, decoded, encoded in datas:
Expand Down
4 changes: 3 additions & 1 deletion tests/test_uper.py
Expand Up @@ -726,6 +726,7 @@ def test_sequence_of(self):
"C ::= SEQUENCE SIZE (1..5) OF INTEGER "
"D ::= SEQUENCE SIZE (1..2, ...) OF INTEGER "
"E ::= SEQUENCE SIZE (1..2, ..., 6..7) OF INTEGER "
"F ::= SEQUENCE SIZE (1..10000) OF OCTET STRING "
"END",
'uper')

Expand All @@ -742,7 +743,8 @@ def test_sequence_of(self):
('D', [2, 1], b'\x40\x40\x80\x40\x40'),
('E',
6 * [1],
b'\x83\x00\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80')
b'\x83\x00\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80'),
('F', 300 * [b'\x56'], b'\x04\xac' + 300 * b'\x05\x58')
]

for type_name, decoded, encoded in datas:
Expand Down

0 comments on commit d84f91a

Please sign in to comment.