@@ -449,6 +449,72 @@ def testLarge2(self):
449449 bytes ((0x06 , 0x13 , 0x88 , 0x37 , 0x83 , 0xC6 , 0xDF , 0xD4 , 0xCC , 0xB3 , 0xFF , 0xFF , 0xFE , 0xF0 , 0xB8 , 0xD6 , 0xB8 , 0xCB , 0xE2 , 0xB6 , 0x47 ))
450450 ) == ((2 , 999 , 18446744073709551535184467440737095 ), b'' )
451451
452+ def testExcessiveContinuationOctets (self ):
453+ """Test that OID arcs with excessive continuation octets are rejected."""
454+ # Create a payload with 25 continuation octets (exceeds 20 limit)
455+ # 0x81 bytes are continuation octets, 0x01 terminates
456+ malicious_payload = bytes ([0x06 , 26 ]) + bytes ([0x81 ] * 25 ) + bytes ([0x01 ])
457+ try :
458+ decoder .decode (malicious_payload )
459+ except error .PyAsn1Error :
460+ pass
461+ else :
462+ assert 0 , 'Excessive continuation octets tolerated'
463+
464+ def testMaxAllowedContinuationOctets (self ):
465+ """Test that OID arcs at the maximum continuation octets limit work."""
466+ # Create a payload with exactly 20 continuation octets (at limit)
467+ # This should succeed
468+ payload = bytes ([0x06 , 21 ]) + bytes ([0x81 ] * 20 ) + bytes ([0x01 ])
469+ try :
470+ decoder .decode (payload )
471+ except error .PyAsn1Error :
472+ assert 0 , 'Valid OID with 20 continuation octets rejected'
473+
474+ def testOneOverContinuationLimit (self ):
475+ """Test boundary: 21 continuation octets (one over limit) is rejected."""
476+ payload = bytes ([0x06 , 22 ]) + bytes ([0x81 ] * 21 ) + bytes ([0x01 ])
477+ try :
478+ decoder .decode (payload )
479+ except error .PyAsn1Error :
480+ pass
481+ else :
482+ assert 0 , '21 continuation octets tolerated (should be rejected)'
483+
484+ def testExcessiveContinuationInSecondArc (self ):
485+ """Test that limit applies to subsequent arcs, not just the first."""
486+ # First arc: valid simple byte (0x55 = 85, decodes to arc 2.5)
487+ # Second arc: excessive continuation octets
488+ payload = bytes ([0x06 , 27 ]) + bytes ([0x55 ]) + bytes ([0x81 ] * 25 ) + bytes ([0x01 ])
489+ try :
490+ decoder .decode (payload )
491+ except error .PyAsn1Error :
492+ pass
493+ else :
494+ assert 0 , 'Excessive continuation in second arc tolerated'
495+
496+ def testMultipleArcsAtLimit (self ):
497+ """Test multiple arcs each at the continuation limit work correctly."""
498+ # Two arcs, each with 20 continuation octets (both at limit)
499+ arc1 = bytes ([0x81 ] * 20 ) + bytes ([0x01 ]) # 21 bytes
500+ arc2 = bytes ([0x81 ] * 20 ) + bytes ([0x01 ]) # 21 bytes
501+ payload = bytes ([0x06 , 42 ]) + arc1 + arc2
502+ try :
503+ decoder .decode (payload )
504+ except error .PyAsn1Error :
505+ assert 0 , 'Multiple valid arcs at limit rejected'
506+
507+ def testExcessiveContinuationWithMaxBytes (self ):
508+ """Test with 0xFF continuation bytes (maximum value, not just 0x81)."""
509+ # 0xFF bytes are also continuation octets (high bit set)
510+ malicious_payload = bytes ([0x06 , 26 ]) + bytes ([0xFF ] * 25 ) + bytes ([0x01 ])
511+ try :
512+ decoder .decode (malicious_payload )
513+ except error .PyAsn1Error :
514+ pass
515+ else :
516+ assert 0 , 'Excessive 0xFF continuation octets tolerated'
517+
452518
453519class RelativeOIDDecoderTestCase (BaseTestCase ):
454520 def testOne (self ):
@@ -518,6 +584,70 @@ def testLarge(self):
518584 bytes ((0x0D , 0x13 , 0x88 , 0x37 , 0x83 , 0xC6 , 0xDF , 0xD4 , 0xCC , 0xB3 , 0xFF , 0xFF , 0xFE , 0xF0 , 0xB8 , 0xD6 , 0xB8 , 0xCB , 0xE2 , 0xB6 , 0x47 ))
519585 ) == ((1079 , 18446744073709551535184467440737095 ), b'' )
520586
587+ def testExcessiveContinuationOctets (self ):
588+ """Test that RELATIVE-OID arcs with excessive continuation octets are rejected."""
589+ # Create a payload with 25 continuation octets (exceeds 20 limit)
590+ malicious_payload = bytes ([0x0D , 26 ]) + bytes ([0x81 ] * 25 ) + bytes ([0x01 ])
591+ try :
592+ decoder .decode (malicious_payload )
593+ except error .PyAsn1Error :
594+ pass
595+ else :
596+ assert 0 , 'Excessive continuation octets tolerated'
597+
598+ def testMaxAllowedContinuationOctets (self ):
599+ """Test that RELATIVE-OID arcs at the maximum continuation octets limit work."""
600+ # Create a payload with exactly 20 continuation octets (at limit)
601+ payload = bytes ([0x0D , 21 ]) + bytes ([0x81 ] * 20 ) + bytes ([0x01 ])
602+ try :
603+ decoder .decode (payload )
604+ except error .PyAsn1Error :
605+ assert 0 , 'Valid RELATIVE-OID with 20 continuation octets rejected'
606+
607+ def testOneOverContinuationLimit (self ):
608+ """Test boundary: 21 continuation octets (one over limit) is rejected."""
609+ payload = bytes ([0x0D , 22 ]) + bytes ([0x81 ] * 21 ) + bytes ([0x01 ])
610+ try :
611+ decoder .decode (payload )
612+ except error .PyAsn1Error :
613+ pass
614+ else :
615+ assert 0 , '21 continuation octets tolerated (should be rejected)'
616+
617+ def testExcessiveContinuationInSecondArc (self ):
618+ """Test that limit applies to subsequent arcs, not just the first."""
619+ # First arc: valid simple byte
620+ # Second arc: excessive continuation octets
621+ payload = bytes ([0x0D , 27 ]) + bytes ([0x55 ]) + bytes ([0x81 ] * 25 ) + bytes ([0x01 ])
622+ try :
623+ decoder .decode (payload )
624+ except error .PyAsn1Error :
625+ pass
626+ else :
627+ assert 0 , 'Excessive continuation in second arc tolerated'
628+
629+ def testMultipleArcsAtLimit (self ):
630+ """Test multiple arcs each at the continuation limit work correctly."""
631+ # Two arcs, each with 20 continuation octets (both at limit)
632+ arc1 = bytes ([0x81 ] * 20 ) + bytes ([0x01 ]) # 21 bytes
633+ arc2 = bytes ([0x81 ] * 20 ) + bytes ([0x01 ]) # 21 bytes
634+ payload = bytes ([0x0D , 42 ]) + arc1 + arc2
635+ try :
636+ decoder .decode (payload )
637+ except error .PyAsn1Error :
638+ assert 0 , 'Multiple valid arcs at limit rejected'
639+
640+ def testExcessiveContinuationWithMaxBytes (self ):
641+ """Test with 0xFF continuation bytes (maximum value, not just 0x81)."""
642+ # 0xFF bytes are also continuation octets (high bit set)
643+ malicious_payload = bytes ([0x0D , 26 ]) + bytes ([0xFF ] * 25 ) + bytes ([0x01 ])
644+ try :
645+ decoder .decode (malicious_payload )
646+ except error .PyAsn1Error :
647+ pass
648+ else :
649+ assert 0 , 'Excessive 0xFF continuation octets tolerated'
650+
521651
522652class RealDecoderTestCase (BaseTestCase ):
523653 def testChar (self ):
0 commit comments