From 825e9c706e9f79bc0034bcc755096b5c8abd4515 Mon Sep 17 00:00:00 2001 From: elie Date: Thu, 31 Oct 2013 21:28:57 +0000 Subject: ObjectIdentifier codec fixed to work properly with arc 0 and arc 2 values --- CHANGES | 1 + pyasn1/codec/ber/decoder.py | 16 +++++++++++++--- pyasn1/codec/ber/encoder.py | 18 ++++++++++++++---- test/codec/ber/test_decoder.py | 14 ++++++++++---- test/codec/ber/test_encoder.py | 19 +++++++++++++++++-- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 43374eb..414efc5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ Revision 0.1.8 -------------- +- ObjectIdentifier codec fixed to work properly with arc 0 and arc 2 values. - Unicode initializer support added to OctetString type and derivatives. - Fix to SEQUENCE and SET types to give them their private componentTypes collection (which is a NamedTypes object) so that they won't collide in diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 2c6896f..1530a54 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -216,14 +216,24 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder): if not head: raise error.PyAsn1Error('Empty substrate') - # Get the first subid + # Decode the first octet + index = 1 subId = oct2int(head[0]) - oid = divmod(subId, 40) + if 0 <= subId <= 39: + oid = 0, subId + elif 40 <= subId <= 79: + oid = 1, subId - 40 + elif subId >= 80: + oid = 2, + index = 0 + else: + raise error.PyAsn1Error('Malformed first OID octet: %s' % subId) - index = 1 substrateLen = len(head) while index < substrateLen: subId = oct2int(head[index]) + if index == 0: + subId -= 80 index = index + 1 if subId == 128: # ASN.1 spec forbids leading zeros (0x80) in sub-ID OID diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index cfb59a8..c4db49e 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -166,13 +166,20 @@ class ObjectIdentifierEncoder(AbstractItemEncoder): if len(oid) < 2: raise error.PyAsn1Error('Short OID %s' % (value,)) + index = 2 + # Build the first twos - if oid[0] > 6 or oid[1] > 39 or oid[0] == 6 and oid[1] > 15: + if oid[0] == 0 and 0 <= oid[1] <= 39: + octets = (oid[1],) + elif oid[0] == 1 and 0 <= oid[1] <= 39: + octets = (oid[1] + 40,) + elif oid[0] == 2: + octets = () + index = 1 + else: raise error.PyAsn1Error( 'Initial sub-ID overflow %s in OID %s' % (oid[:2], value) ) - octets = (oid[0] * 40 + oid[1],) - index = 2 # Cycle through subids for subid in oid[index:]: @@ -192,7 +199,10 @@ class ObjectIdentifierEncoder(AbstractItemEncoder): subid = subid >> 7 # Add packed Sub-Object ID to resulted Object ID octets += res - + + if index == 1: + octets = (octets[0]+80,) + octets[1:] + return ints2octs(octets), 0 class RealEncoder(AbstractItemEncoder): diff --git a/test/codec/ber/test_decoder.py b/test/codec/ber/test_decoder.py index b581bc6..294e0ce 100644 --- a/test/codec/ber/test_decoder.py +++ b/test/codec/ber/test_decoder.py @@ -187,13 +187,19 @@ class ObjectIdentifierDecoderTestCase(unittest.TestCase): def testEdges1(self): assert decoder.decode( - ints2octs((6, 1, 255)) - ) == ((6,15), null) + ints2octs((6, 1, 39)) + ) == ((0,39), null) def testEdges2(self): assert decoder.decode( - ints2octs((6, 1, 239)) - ) == ((5,39), null) + ints2octs((6, 1, 79)) + ) == ((1,39), null) + + def testEdges3(self): + assert decoder.decode( + ints2octs((6, 5, 223, 255, 255, 255, 127)) + ) == ((2,0xffffffff), null) + def testEdges3(self): assert decoder.decode( diff --git a/test/codec/ber/test_encoder.py b/test/codec/ber/test_encoder.py index edf43b0..3a0a1b2 100644 --- a/test/codec/ber/test_encoder.py +++ b/test/codec/ber/test_encoder.py @@ -132,10 +132,25 @@ class NullEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Null('')) == ints2octs((5, 0)) class ObjectIdentifierEncoderTestCase(unittest.TestCase): - def testNull(self): + def testOne(self): assert encoder.encode( univ.ObjectIdentifier((1,3,6,0,0xffffe)) - ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) + ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) + + def testEdge1(self): + assert encoder.encode( + univ.ObjectIdentifier((0,39)) + ) == ints2octs((6,1,39)) + + def testEdge2(self): + assert encoder.encode( + univ.ObjectIdentifier((1,39)) + ) == ints2octs((6,1,79)) + + def testEdge3(self): + assert encoder.encode( + univ.ObjectIdentifier((2,0xffffffff)) + ) == ints2octs((6, 5, 223, 255, 255, 255, 127)) class RealEncoderTestCase(unittest.TestCase): def testChar(self): -- cgit v1.2.1