diff options
author | Ilya Etingof <etingof@gmail.com> | 2017-09-14 01:26:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-14 01:26:54 +0200 |
commit | 1200e9cac5899a76563fbed4eedcc64ba5819238 (patch) | |
tree | 1866c4836169b604b2f95fce58b0606958641f02 | |
parent | 5359bf1df4e64c1f2f19bff69670ed2f213d8c21 (diff) | |
parent | 1183c6c9724de537971903a66b537144fe39111f (diff) | |
download | pyasn1-git-1200e9cac5899a76563fbed4eedcc64ba5819238.tar.gz |
Merge pull request #75 from etingof/enforce-codecs-properties
ASN.1 codecs to silently enforce proper length/chunk modes
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | pyasn1/codec/ber/encoder.py | 11 | ||||
-rw-r--r-- | pyasn1/codec/cer/encoder.py | 25 | ||||
-rw-r--r-- | pyasn1/codec/der/encoder.py | 24 | ||||
-rw-r--r-- | tests/codec/der/test_encoder.py | 23 |
5 files changed, 26 insertions, 60 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index b1bfea4..7d7ff33 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Revision 0.3.5, released XX-09-2017 - Codecs signatures unified and pass **options through the call chain - Explicit tag encoding optimized to avoid unnecessary copying - End-of-octets sentinel encoding optimized +- Refactored ASN.1 codecs properties to silently enforce proper length and + chunk size encoding modes +- Fixed DER encoder to always produce primitive encoding Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index dee13e5..b43e209 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -460,7 +460,8 @@ typeMap = { class Encoder(object): - supportIndefLength = True + fixedDefLengthMode = None + fixedChunkSize = None # noinspection PyDefaultArgument def __init__(self, tagMap, typeMap={}): @@ -468,8 +469,6 @@ class Encoder(object): self.__typeMap = typeMap def __call__(self, value, **options): - if not options.get('defMode', True) and not self.supportIndefLength: - raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') if debug.logger & debug.flagEncoder: logger = debug.logger @@ -479,6 +478,12 @@ class Encoder(object): if logger: logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint())) + if self.fixedDefLengthMode is not None: + options.update(defMode=self.fixedDefLengthMode) + + if self.fixedChunkSize is not None: + options.update(maxChunkSize=self.fixedChunkSize) + tagSet = value.tagSet try: diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index 50cb346..dd3e2b4 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -22,22 +22,6 @@ class BooleanEncoder(encoder.IntegerEncoder): return substrate, False, False -class BitStringEncoder(encoder.BitStringEncoder): - def encodeValue(self, value, encodeFun, **options): - options.update(maxChunkSize=1000) - return encoder.BitStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - - -class OctetStringEncoder(encoder.OctetStringEncoder): - def encodeValue(self, value, encodeFun, **options): - options.update(maxChunkSize=1000) - return encoder.OctetStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - - class RealEncoder(encoder.RealEncoder): def _chooseEncBase(self, value): m, b, e = value @@ -83,7 +67,7 @@ class TimeEncoderMixIn(object): ) -class GeneralizedTimeEncoder(TimeEncoderMixIn, OctetStringEncoder): +class GeneralizedTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder): minLength = 12 maxLength = 19 @@ -181,8 +165,6 @@ class SequenceOfEncoder(encoder.SequenceOfEncoder): tagMap = encoder.tagMap.copy() tagMap.update({ univ.Boolean.tagSet: BooleanEncoder(), - univ.BitString.tagSet: BitStringEncoder(), - univ.OctetString.tagSet: OctetStringEncoder(), univ.Real.tagSet: RealEncoder(), useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(), useful.UTCTime.tagSet: UTCTimeEncoder(), @@ -194,8 +176,6 @@ tagMap.update({ typeMap = encoder.typeMap.copy() typeMap.update({ univ.Boolean.typeId: BooleanEncoder(), - univ.BitString.typeId: BitStringEncoder(), - univ.OctetString.typeId: OctetStringEncoder(), univ.Real.typeId: RealEncoder(), useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(), useful.UTCTime.typeId: UTCTimeEncoder(), @@ -208,7 +188,8 @@ typeMap.update({ class Encoder(encoder.Encoder): - supportIndefLength = True + fixedDefLengthMode = False + fixedChunkSize = 1000 def __call__(self, value, **options): if 'defMode' not in options: diff --git a/pyasn1/codec/der/encoder.py b/pyasn1/codec/der/encoder.py index 59dd512..d2992a9 100644 --- a/pyasn1/codec/der/encoder.py +++ b/pyasn1/codec/der/encoder.py @@ -10,18 +10,6 @@ from pyasn1.codec.cer import encoder __all__ = ['encode'] -class BitStringEncoder(encoder.BitStringEncoder): - def encodeValue(self, value, encodeFun, **options): - return encoder.BitStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - -class OctetStringEncoder(encoder.OctetStringEncoder): - def encodeValue(self, value, encodeFun, **options): - return encoder.OctetStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - class SetOfEncoder(encoder.SetOfEncoder): @staticmethod def _sortComponents(components): @@ -30,16 +18,12 @@ class SetOfEncoder(encoder.SetOfEncoder): tagMap = encoder.tagMap.copy() tagMap.update({ - univ.BitString.tagSet: BitStringEncoder(), - univ.OctetString.tagSet: OctetStringEncoder(), # Set & SetOf have same tags univ.SetOf.tagSet: SetOfEncoder() }) typeMap = encoder.typeMap.copy() typeMap.update({ - univ.BitString.typeId: BitStringEncoder(), - univ.OctetString.typeId: OctetStringEncoder(), # Set & SetOf have same tags univ.Set.typeId: SetOfEncoder(), univ.SetOf.typeId: SetOfEncoder() @@ -47,12 +31,8 @@ typeMap.update({ class Encoder(encoder.Encoder): - supportIndefLength = False - - def __call__(self, value, **options): - if 'defMode' not in options: - options.update(defMode=True) - return encoder.Encoder.__call__(self, value, **options) + fixedDefLengthMode = True + fixedChunkSize = 0 #: Turns ASN.1 object into DER octet stream. #: diff --git a/tests/codec/der/test_encoder.py b/tests/codec/der/test_encoder.py index d30dfc1..354781a 100644 --- a/tests/codec/der/test_encoder.py +++ b/tests/codec/der/test_encoder.py @@ -17,31 +17,28 @@ from pyasn1.error import PyAsn1Error class OctetStringEncoderTestCase(unittest.TestCase): - def testShortMode(self): + def testDefModeShort(self): assert encoder.encode( univ.OctetString('Quick brown fox') ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) - def testIndefMode(self): - try: - encoder.encode(univ.OctetString('Quick brown'), defMode=False) - except PyAsn1Error: - pass - else: - assert 0, 'Indefinite length encoding tolerated' - - def testChunkedMode(self): + def testDefModeLong(self): assert encoder.encode( - univ.OctetString('Quick brown'), maxChunkSize=2 - ) == ints2octs((4, 11, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + univ.OctetString('Q' * 10000) + ) == ints2octs((4, 130, 39, 16) + (81,) * 10000) class BitStringEncoderTestCase(unittest.TestCase): - def testShortMode(self): + def testDefModeShort(self): assert encoder.encode( univ.BitString((1,)) ) == ints2octs((3, 2, 7, 128)) + def testDefModeLong(self): + assert encoder.encode( + univ.BitString((1,) * 80000) + ) == ints2octs((3, 130, 39, 17, 0) + (255,) * 10000) + class SetOfEncoderTestCase(unittest.TestCase): def setUp(self): |