Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pyasn1 for openSUSE:Factory 
checked in at 2026-07-20 09:57:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyasn1 (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyasn1.new.24530 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyasn1"

Mon Jul 20 09:57:09 2026 rev:50 rq:1366344 version:0.6.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyasn1/python-pyasn1.changes      
2026-07-15 16:31:10.417146088 +0200
+++ /work/SRC/openSUSE:Factory/.python-pyasn1.new.24530/python-pyasn1.changes   
2026-07-20 09:59:46.216998802 +0200
@@ -1,0 +2,24 @@
+Thu Jul 16 08:56:13 UTC 2026 - Nico Krapp <[email protected]>
+
+- Update to 0.6.4 (fixes CVE-2026-59884 (bsc#1271464),
+  CVE-2026-59885 (bsc#1271465), CVE-2026-59886 (bsc#1271466))
+  * CVE-2026-59885 (GHSA-8ppf-4f7h-5ppj): Fixed quadratic time complexity in
+    the OBJECT IDENTIFIER and RELATIVE-OID decoders. A small crafted substrate
+    encoding many arcs could consume excessive CPU. Arcs are now accumulated in
+    linear time; decoded values are unchanged
+  * CVE-2026-59884 (GHSA-m4p7-r5rc-7g4j): Limited BER long-form tag IDs to 20
+    octets (140 bits), matching the OID arc limit introduced in 0.6.2.
+    Unbounded tag IDs allowed a crafted substrate to consume excessive CPU and
+    memory; longer tag IDs are now rejected with PyAsn1Error. Also fixed Tag
+    and TagSet repr() failing on huge tag IDs due to the integer-to-string
+    conversion limit
+  * CVE-2026-59886 (GHSA-hm4w-wwcw-mr6r): Fixed excessive memory and CPU
+    consumption in Real.__float__() for values with large base-10 exponents.
+    Conversion no longer materializes huge intermediate integers; values too
+    large to represent as a Python float raise OverflowError promptly, and
+    prettyPrint() renders them as '<overflow>' as before. Also fixed base-10
+    mantissa normalization to use exact integer arithmetic; mantissas larger
+    than 2**53 could previously lose precision through float division
+  * Pinned PyPI publish GitHub Action to an immutable commit
+
+-------------------------------------------------------------------

Old:
----
  pyasn1-0.6.3.tar.gz

New:
----
  pyasn1-0.6.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pyasn1.spec ++++++
--- /var/tmp/diff_new_pack.iXkzSW/_old  2026-07-20 09:59:46.661013744 +0200
+++ /var/tmp/diff_new_pack.iXkzSW/_new  2026-07-20 09:59:46.665013879 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-pyasn1
-Version:        0.6.3
+Version:        0.6.4
 Release:        0
 Summary:        ASN.1 types and codecs
 License:        BSD-2-Clause

++++++ pyasn1-0.6.3.tar.gz -> pyasn1-0.6.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/CHANGES.rst new/pyasn1-0.6.4/CHANGES.rst
--- old/pyasn1-0.6.3/CHANGES.rst        2026-03-17 02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/CHANGES.rst        2026-07-09 03:12:14.000000000 +0200
@@ -1,3 +1,30 @@
+Revision 0.6.4, released 08-07-2026
+---------------------------------------
+
+- CVE-2026-59885 (GHSA-8ppf-4f7h-5ppj): Fixed quadratic time
+  complexity in the OBJECT IDENTIFIER and RELATIVE-OID decoders.
+  A small crafted substrate encoding many arcs could consume
+  excessive CPU. Arcs are now accumulated in linear time; decoded
+  values are unchanged (thanks for reporting, tynus2)
+- CVE-2026-59884 (GHSA-m4p7-r5rc-7g4j): Limited BER long-form tag
+  IDs to 20 octets (140 bits), matching the OID arc limit introduced
+  in 0.6.2. Unbounded tag IDs allowed a crafted substrate to consume
+  excessive CPU and memory; longer tag IDs are now rejected with
+  PyAsn1Error. Also fixed Tag and TagSet repr() failing on huge tag
+  (thanks for reporting, mikeappsec)
+  IDs due to the integer-to-string conversion limit (Python 3.11+)
+- CVE-2026-59886 (GHSA-hm4w-wwcw-mr6r): Fixed excessive memory and
+  CPU consumption in Real.__float__() for values with large base-10
+  exponents. Conversion no longer materializes huge intermediate
+  integers; values too large to represent as a Python float raise
+  OverflowError promptly, and prettyPrint() renders them as
+  '<overflow>' as before. Also fixed base-10 mantissa normalization
+  to use exact integer arithmetic; mantissas larger than 2**53
+  could previously lose precision through float division
+  (thanks for reporting, gvozdila)
+- Pinned PyPI publish GitHub Action to an immutable commit
+  [pr #113](https://github.com/pyasn1/pyasn1/pull/113)
+
 Revision 0.6.3, released 16-03-2026
 ---------------------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/PKG-INFO new/pyasn1-0.6.4/PKG-INFO
--- old/pyasn1-0.6.3/PKG-INFO   2026-03-17 02:06:42.622166200 +0100
+++ new/pyasn1-0.6.4/PKG-INFO   2026-07-09 03:12:22.895374300 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: pyasn1
-Version: 0.6.3
+Version: 0.6.4
 Summary: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs 
(X.208)
 Author-email: Ilya Etingof <[email protected]>
 Maintainer: pyasn1 maintenance organization
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/pyasn1/__init__.py 
new/pyasn1-0.6.4/pyasn1/__init__.py
--- old/pyasn1-0.6.3/pyasn1/__init__.py 2026-03-17 02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/pyasn1/__init__.py 2026-07-09 03:12:14.000000000 +0200
@@ -1,2 +1,2 @@
 # https://www.python.org/dev/peps/pep-0396/
-__version__ = '0.6.3'
+__version__ = '0.6.4'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/pyasn1/codec/ber/decoder.py 
new/pyasn1-0.6.4/pyasn1/codec/ber/decoder.py
--- old/pyasn1-0.6.3/pyasn1/codec/ber/decoder.py        2026-03-17 
02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/pyasn1/codec/ber/decoder.py        2026-07-09 
03:12:14.000000000 +0200
@@ -36,6 +36,10 @@
 # Maximum number of continuation octets (high-bit set) allowed per OID arc.
 # 20 octets allows up to 140-bit integers, supporting UUID-based OIDs
 MAX_OID_ARC_CONTINUATION_OCTETS = 20
+
+# Maximum number of octets in a long-form tag ID (20 octets = up to
+# 140-bit tag IDs, matching the OID arc limit)
+MAX_TAG_OCTETS = 20
 MAX_NESTING_DEPTH = 100
 
 # Maximum number of bytes in a BER length field (8 bytes = up to 2^64-1)
@@ -423,14 +427,14 @@
         if not chunk:
             raise error.PyAsn1Error('Empty substrate')
 
-        oid = ()
+        oid = []
         index = 0
         substrateLen = len(chunk)
         while index < substrateLen:
             subId = chunk[index]
             index += 1
             if subId < 128:
-                oid += (subId,)
+                oid.append(subId)
             elif subId > 128:
                 # Construct subid from a number of octets
                 nextSubId = subId
@@ -446,11 +450,11 @@
                     subId = (subId << 7) + (nextSubId & 0x7F)
                     if index >= substrateLen:
                         raise error.SubstrateUnderrunError(
-                            'Short substrate for sub-OID past %s' % (oid,)
+                            'Short substrate for sub-OID past %s' % 
(tuple(oid),)
                         )
                     nextSubId = chunk[index]
                     index += 1
-                oid += ((subId << 7) + nextSubId,)
+                oid.append((subId << 7) + nextSubId)
             elif subId == 128:
                 # ASN.1 spec forbids leading zeros (0x80) in OID
                 # encoding, tolerating it opens a vulnerability. See
@@ -460,15 +464,17 @@
 
         # Decode two leading arcs
         if 0 <= oid[0] <= 39:
-            oid = (0,) + oid
+            oid.insert(0, 0)
         elif 40 <= oid[0] <= 79:
-            oid = (1, oid[0] - 40) + oid[1:]
+            oid[0] -= 40
+            oid.insert(0, 1)
         elif oid[0] >= 80:
-            oid = (2, oid[0] - 80) + oid[1:]
+            oid[0] -= 80
+            oid.insert(0, 2)
         else:
             raise error.PyAsn1Error('Malformed first OID octet: %s' % chunk[0])
 
-        yield self._createComponent(asn1Spec, tagSet, oid, **options)
+        yield self._createComponent(asn1Spec, tagSet, tuple(oid), **options)
 
 
 class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder):
@@ -488,14 +494,14 @@
         if not chunk:
             raise error.PyAsn1Error('Empty substrate')
 
-        reloid = ()
+        reloid = []
         index = 0
         substrateLen = len(chunk)
         while index < substrateLen:
             subId = chunk[index]
             index += 1
             if subId < 128:
-                reloid += (subId,)
+                reloid.append(subId)
             elif subId > 128:
                 # Construct subid from a number of octets
                 nextSubId = subId
@@ -511,11 +517,11 @@
                     subId = (subId << 7) + (nextSubId & 0x7F)
                     if index >= substrateLen:
                         raise error.SubstrateUnderrunError(
-                            'Short substrate for sub-OID past %s' % (reloid,)
+                            'Short substrate for sub-OID past %s' % 
(tuple(reloid),)
                         )
                     nextSubId = chunk[index]
                     index += 1
-                reloid += ((subId << 7) + nextSubId,)
+                reloid.append((subId << 7) + nextSubId)
             elif subId == 128:
                 # ASN.1 spec forbids leading zeros (0x80) in OID
                 # encoding, tolerating it opens a vulnerability. See
@@ -523,7 +529,7 @@
                 # page 7
                 raise error.PyAsn1Error('Invalid octet 0x80 in RELATIVE-OID 
encoding')
 
-        yield self._createComponent(asn1Spec, tagSet, reloid, **options)
+        yield self._createComponent(asn1Spec, tagSet, tuple(reloid), **options)
 
 
 class RealPayloadDecoder(AbstractSimplePayloadDecoder):
@@ -1633,7 +1639,7 @@
 
                     if tagId == 0x1F:
                         isShortTag = False
-                        lengthOctetIdx = 0
+                        tagOctetCount = 0
                         tagId = 0
 
                         while True:
@@ -1647,7 +1653,12 @@
                                 )
 
                             integerTag = ord(integerByte)
-                            lengthOctetIdx += 1
+                            tagOctetCount += 1
+                            if tagOctetCount > MAX_TAG_OCTETS:
+                                raise error.PyAsn1Error(
+                                    'Tag ID octet count exceeds limit (%d)' % (
+                                        MAX_TAG_OCTETS,)
+                                )
                             tagId <<= 7
                             tagId |= (integerTag & 0x7F)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/pyasn1/codec/ber/encoder.py 
new/pyasn1-0.6.4/pyasn1/codec/ber/encoder.py
--- old/pyasn1-0.6.3/pyasn1/codec/ber/encoder.py        2026-03-17 
02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/pyasn1/codec/ber/encoder.py        2026-07-09 
03:12:14.000000000 +0200
@@ -325,30 +325,30 @@
         else:
             raise error.PyAsn1Error('Impossible first/second arcs at %s' % 
(value,))
 
-        octets = ()
+        octets = []
 
         # Cycle through subIds
         for subOid in oid:
             if 0 <= subOid <= 127:
                 # Optimize for the common case
-                octets += (subOid,)
+                octets.append(subOid)
 
             elif subOid > 127:
                 # Pack large Sub-Object IDs
-                res = (subOid & 0x7f,)
+                res = [subOid & 0x7f]
                 subOid >>= 7
 
                 while subOid:
-                    res = (0x80 | (subOid & 0x7f),) + res
+                    res.append(0x80 | (subOid & 0x7f))
                     subOid >>= 7
 
                 # Add packed Sub-Object ID to resulted Object ID
-                octets += res
+                octets.extend(reversed(res))
 
             else:
                 raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, 
value))
 
-        return octets, False, False
+        return tuple(octets), False, False
 
 
 class RelativeOIDEncoder(AbstractItemEncoder):
@@ -358,30 +358,30 @@
         if asn1Spec is not None:
             value = asn1Spec.clone(value)
 
-        octets = ()
+        octets = []
 
         # Cycle through subIds
         for subOid in value.asTuple():
             if 0 <= subOid <= 127:
                 # Optimize for the common case
-                octets += (subOid,)
+                octets.append(subOid)
 
             elif subOid > 127:
                 # Pack large Sub-Object IDs
-                res = (subOid & 0x7f,)
+                res = [subOid & 0x7f]
                 subOid >>= 7
 
                 while subOid:
-                    res = (0x80 | (subOid & 0x7f),) + res
+                    res.append(0x80 | (subOid & 0x7f))
                     subOid >>= 7
 
                 # Add packed Sub-Object ID to resulted RELATIVE-OID
-                octets += res
+                octets.extend(reversed(res))
 
             else:
                 raise error.PyAsn1Error('Negative RELATIVE-OID arc %s at %s' % 
(subOid, value))
 
-        return octets, False, False
+        return tuple(octets), False, False
 
 
 class RealEncoder(AbstractItemEncoder):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/pyasn1/type/tag.py 
new/pyasn1-0.6.4/pyasn1/type/tag.py
--- old/pyasn1-0.6.3/pyasn1/type/tag.py 2026-03-17 02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/pyasn1/type/tag.py 2026-07-09 03:12:14.000000000 +0200
@@ -34,6 +34,16 @@
 tagCategoryUntagged = 0x04
 
 
+def _tagIdToStr(tagId):
+    # Decimal rendering of a huge tag ID can exceed the interpreter's
+    # integer-to-string conversion limit (sys.get_int_max_str_digits(),
+    # Python 3.11+) and raise ValueError; hexadecimal is not limited
+    try:
+        return str(tagId)
+    except ValueError:
+        return hex(tagId)
+
+
 class Tag(object):
     """Create ASN.1 tag
 
@@ -56,7 +66,8 @@
     """
     def __init__(self, tagClass, tagFormat, tagId):
         if tagId < 0:
-            raise error.PyAsn1Error('Negative tag ID (%s) not allowed' % tagId)
+            raise error.PyAsn1Error(
+                'Negative tag ID (%s) not allowed' % _tagIdToStr(tagId))
         self.__tagClass = tagClass
         self.__tagFormat = tagFormat
         self.__tagId = tagId
@@ -65,7 +76,7 @@
 
     def __repr__(self):
         representation = '[%s:%s:%s]' % (
-            self.__tagClass, self.__tagFormat, self.__tagId)
+            self.__tagClass, self.__tagFormat, _tagIdToStr(self.__tagId))
         return '<%s object, tag %s>' % (
             self.__class__.__name__, representation)
 
@@ -194,8 +205,9 @@
         self.__hash = hash(self.__superTagsClassId)
 
     def __repr__(self):
-        representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, 
x.tagId)
-                                   for x in self.__superTags])
+        representation = '-'.join(
+            ['%s:%s:%s' % (x.tagClass, x.tagFormat, _tagIdToStr(x.tagId))
+             for x in self.__superTags])
         if representation:
             representation = 'tags ' + representation
         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/pyasn1/type/univ.py 
new/pyasn1-0.6.4/pyasn1/type/univ.py
--- old/pyasn1-0.6.3/pyasn1/type/univ.py        2026-03-17 02:06:33.000000000 
+0100
+++ new/pyasn1-0.6.4/pyasn1/type/univ.py        2026-07-09 03:12:14.000000000 
+0200
@@ -1362,7 +1362,7 @@
     def __normalizeBase10(value):
         m, b, e = value
         while m and m % 10 == 0:
-            m /= 10
+            m //= 10
             e += 1
         return m, b, e
 
@@ -1490,10 +1490,21 @@
     def __float__(self):
         if self._value in self._inf:
             return self._value
-        else:
-            return float(
-                self._value[0] * pow(self._value[1], self._value[2])
-            )
+
+        mantissa, base, exponent = self._value
+
+        if not mantissa:
+            return 0.0
+
+        if base == 2:
+            return math.ldexp(float(mantissa), exponent)
+
+        # base is 10 (prettyIn() rejects everything else); refuse to
+        # materialize astronomically large integers via pow()
+        if exponent > sys.float_info.max_10_exp:
+            raise OverflowError('Real value too large to convert to float')
+
+        return float(mantissa * pow(base, exponent))
 
     def __abs__(self):
         return self.clone(abs(float(self)))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/pyasn1.egg-info/PKG-INFO 
new/pyasn1-0.6.4/pyasn1.egg-info/PKG-INFO
--- old/pyasn1-0.6.3/pyasn1.egg-info/PKG-INFO   2026-03-17 02:06:42.000000000 
+0100
+++ new/pyasn1-0.6.4/pyasn1.egg-info/PKG-INFO   2026-07-09 03:12:22.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: pyasn1
-Version: 0.6.3
+Version: 0.6.4
 Summary: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs 
(X.208)
 Author-email: Ilya Etingof <[email protected]>
 Maintainer: pyasn1 maintenance organization
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/tests/codec/ber/test_decoder.py 
new/pyasn1-0.6.4/tests/codec/ber/test_decoder.py
--- old/pyasn1-0.6.3/tests/codec/ber/test_decoder.py    2026-03-17 
02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/tests/codec/ber/test_decoder.py    2026-07-09 
03:12:14.000000000 +0200
@@ -21,10 +21,19 @@
 from pyasn1.type import char
 from pyasn1.codec import streaming
 from pyasn1.codec.ber import decoder
+from pyasn1.codec.ber import encoder
 from pyasn1.codec.ber import eoo
 from pyasn1 import error
 
 
+def encode_length(length):
+    if length < 128:
+        return bytes([length])
+
+    lengthBytes = length.to_bytes((length.bit_length() + 7) // 8, 'big')
+    return bytes([0x80 | len(lengthBytes)]) + lengthBytes
+
+
 class LargeTagDecoderTestCase(BaseTestCase):
     def testLargeTag(self):
         assert decoder.decode(bytes((127, 141, 245, 182, 253, 47, 3, 2, 1, 
1))) == (1, b'')
@@ -32,6 +41,31 @@
     def testLongTag(self):
         assert decoder.decode(bytes((0x1f, 2, 1, 0)))[0].tagSet == 
univ.Integer.tagSet
 
+    def testVeryLongTagRoundTrip(self):
+        # (1 << 140) - 1 is the largest tag ID fitting the 20 octet limit
+        for tagId in (1 << 77, (1 << 140) - 1):
+            largeTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, tagId)
+            asn1Spec = univ.Integer().subtype(implicitTag=largeTag)
+            value = univ.Integer(1).subtype(implicitTag=largeTag)
+
+            decoded, rest = decoder.decode(encoder.encode(value), 
asn1Spec=asn1Spec)
+
+            assert rest == b''
+            assert decoded == 1
+
+    def testExcessiveLongTag(self):
+        # 1 << 140 is the smallest tag ID needing 21 octets, one over the limit
+        excessiveTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1 << 
140)
+        asn1Spec = univ.Integer().subtype(implicitTag=excessiveTag)
+        substrate = 
encoder.encode(univ.Integer(1).subtype(implicitTag=excessiveTag))
+
+        try:
+            decoder.decode(substrate, asn1Spec=asn1Spec)
+        except error.PyAsn1Error:
+            pass
+        else:
+            assert 0, 'excessive long tag tolerated'
+
     def testTagsEquivalence(self):
         integer = 
univ.Integer(2).subtype(implicitTag=tag.Tag(tag.tagClassContext, 0, 0))
         assert decoder.decode(bytes((0x9f, 0x80, 0x00, 0x02, 0x01, 0x02)), 
asn1Spec=integer) == decoder.decode(
@@ -449,6 +483,20 @@
             bytes((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 
0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47))
         ) == ((2, 999, 18446744073709551535184467440737095), b'')
 
+    def testManySingleByteArcs(self):
+        encodedArcCount = 4096
+        substrate = (
+            bytes([0x06]) +
+            encode_length(encodedArcCount) +
+            bytes([0x01] * encodedArcCount)
+        )
+
+        value, rest = decoder.decode(substrate)
+        assert rest == b''
+        assert len(value) == encodedArcCount + 1
+        assert tuple(value[:3]) == (0, 1, 1)
+        assert tuple(value[-3:]) == (1, 1, 1)
+
     def testExcessiveContinuationOctets(self):
         """Test that OID arcs with excessive continuation octets are 
rejected."""
         # Create a payload with 25 continuation octets (exceeds 20 limit)
@@ -584,6 +632,20 @@
             bytes((0x0D, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 
0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47))
         ) == ((1079, 18446744073709551535184467440737095), b'')
 
+    def testManySingleByteArcs(self):
+        arcCount = 4096
+        substrate = (
+            bytes([0x0d]) +
+            encode_length(arcCount) +
+            bytes([0x01] * arcCount)
+        )
+
+        value, rest = decoder.decode(substrate)
+        assert rest == b''
+        assert len(value) == arcCount
+        assert tuple(value[:3]) == (1, 1, 1)
+        assert tuple(value[-3:]) == (1, 1, 1)
+
     def testExcessiveContinuationOctets(self):
         """Test that RELATIVE-OID arcs with excessive continuation octets are 
rejected."""
         # Create a payload with 25 continuation octets (exceeds 20 limit)
@@ -680,17 +742,51 @@
             bytes((9, 4, 161, 255, 1, 3))
         ) == (univ.Real((3, 2, -1020)), b'')
 
-# TODO: this requires Real type comparison fix
+    def testBin6(self):  # large exponent, base = 16
+        value, rest = decoder.decode(
+            bytes((9, 5, 162, 0, 255, 255, 1))
+        )
+
+        assert tuple(value) == (1, 2, 262140)
+        assert rest == b''
+
+    def testBin7(self):  # large exponent in 4-octet form, base = 16
+        value, rest = decoder.decode(
+            bytes((9, 7, 227, 4, 1, 35, 69, 103, 1))
+        )
+
+        assert tuple(value) == (-1, 2, 76354972)
+        assert rest == b''
+
+    def testLargeBinaryRoundTrip(self):
+        substrate = encoder.encode(univ.Real((-1, 2, 76354972)))
+        value, rest = decoder.decode(substrate)
+
+        assert tuple(value) == (-1, 2, 76354972)
+        assert rest == b''
 
-#    def testBin6(self):
-#        assert decoder.decode(
-#            bytes((9, 5, 162, 0, 255, 255, 1))
-#        ) == (univ.Real((1, 2, 262140)), b'')
-
-#    def testBin7(self):
-#        assert decoder.decode(
-#            bytes((9, 7, 227, 4, 1, 35, 69, 103, 1))
-#        ) == (univ.Real((-1, 2, 76354972)), b'')
+    def testLongFormBinaryRealExponentLength(self):
+        value, rest = decoder.decode(
+            bytes((9, 6, 0x83, 3, 0x0f, 0x42, 0x40, 1))
+        )
+
+        assert tuple(value) == (1, 2, 1000000)
+        assert rest == b''
+
+    def testLargeBinaryPrettyPrintOverflow(self):
+        value, rest = decoder.decode(
+            b'\t\t\xeb\x060662.666\xd0B\x00\x00\x00\x00\x00\x00\x00'
+        )
+
+        assert value.prettyPrint() == '<overflow>'
+        assert rest == b'6\xd0B\x00\x00\x00\x00\x00\x00\x00'
+
+        try:
+            float(value)
+        except OverflowError:
+            pass
+        else:
+            assert 0, '__float__() tolerated overflow'
 
     def testPlusInf(self):
         assert decoder.decode(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/tests/codec/ber/test_encoder.py 
new/pyasn1-0.6.4/tests/codec/ber/test_encoder.py
--- old/pyasn1-0.6.3/tests/codec/ber/test_encoder.py    2026-03-17 
02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/tests/codec/ber/test_encoder.py    2026-07-09 
03:12:14.000000000 +0200
@@ -348,6 +348,16 @@
         ) == bytes((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 
0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6,
                         0xB8, 0xCB, 0xE2, 0xB6, 0x47))
 
+    def testManySingleByteArcs(self):
+        arcCount = 4096
+        substrate = encoder.encode(
+            univ.ObjectIdentifier((1, 3) + (1,) * arcCount)
+        )
+
+        assert substrate == (
+            bytes([0x06, 0x82, 0x10, 0x01, 0x2B]) + bytes([0x01] * arcCount)
+        )
+
 
 class ObjectIdentifierWithSchemaEncoderTestCase(BaseTestCase):
     def testOne(self):
@@ -379,6 +389,16 @@
                         0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB,
                         0xE2, 0xB6, 0x47))
 
+    def testManySingleByteArcs(self):
+        arcCount = 4096
+        substrate = encoder.encode(
+            univ.RelativeOID((1,) * arcCount)
+        )
+
+        assert substrate == (
+            bytes([0x0D, 0x82, 0x10, 0x00]) + bytes([0x01] * arcCount)
+        )
+
 
 class RelativeOIDWithSchemaEncoderTestCase(BaseTestCase):
     def testOne(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/tests/codec/cer/test_decoder.py 
new/pyasn1-0.6.4/tests/codec/cer/test_decoder.py
--- old/pyasn1-0.6.3/tests/codec/cer/test_decoder.py    2026-03-17 
02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/tests/codec/cer/test_decoder.py    2026-07-09 
03:12:14.000000000 +0200
@@ -14,6 +14,7 @@
 from pyasn1.type import opentype
 from pyasn1.type import univ
 from pyasn1.codec.cer import decoder
+from pyasn1.codec.cer import encoder
 from pyasn1.error import PyAsn1Error
 
 
@@ -65,6 +66,30 @@
     # TODO: test failures on short chunked and long unchunked substrate samples
 
 
+class LargeTagDecoderTestCase(BaseTestCase):
+    def testExcessiveLongTag(self):
+        # 1 << 140 is the smallest tag ID needing 21 octets, one over the limit
+        excessiveTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1 << 
140)
+        asn1Spec = univ.Integer().subtype(implicitTag=excessiveTag)
+        substrate = 
encoder.encode(univ.Integer(1).subtype(implicitTag=excessiveTag))
+
+        try:
+            decoder.decode(substrate, asn1Spec=asn1Spec)
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'excessive long tag tolerated'
+
+
+class RealDecoderTestCase(BaseTestCase):
+    def testLargeBinaryRoundTrip(self):
+        substrate = encoder.encode(univ.Real((-1, 2, 76354972)))
+        value, rest = decoder.decode(substrate)
+
+        assert tuple(value) == (-1, 2, 76354972)
+        assert rest == b''
+
+
 class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase):
     def setUp(self):
         openType = opentype.OpenType(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/tests/codec/der/test_decoder.py 
new/pyasn1-0.6.4/tests/codec/der/test_decoder.py
--- old/pyasn1-0.6.3/tests/codec/der/test_decoder.py    2026-03-17 
02:06:33.000000000 +0100
+++ new/pyasn1-0.6.4/tests/codec/der/test_decoder.py    2026-07-09 
03:12:14.000000000 +0200
@@ -14,6 +14,7 @@
 from pyasn1.type import opentype
 from pyasn1.type import univ
 from pyasn1.codec.der import decoder
+from pyasn1.codec.der import encoder
 from pyasn1.error import PyAsn1Error
 
 
@@ -71,6 +72,39 @@
             assert 0, 'chunked encoding tolerated'
 
 
+class LargeTagDecoderTestCase(BaseTestCase):
+    def testExcessiveLongTag(self):
+        # 1 << 140 is the smallest tag ID needing 21 octets, one over the limit
+        excessiveTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1 << 
140)
+        asn1Spec = univ.Integer().subtype(implicitTag=excessiveTag)
+        substrate = 
encoder.encode(univ.Integer(1).subtype(implicitTag=excessiveTag))
+
+        try:
+            decoder.decode(substrate, asn1Spec=asn1Spec)
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'excessive long tag tolerated'
+
+
+class RealDecoderTestCase(BaseTestCase):
+    def testCanonicalLargeBinaryReal(self):
+        substrate = encoder.encode(univ.Real((1, 2, 1000000)))
+        assert substrate == bytes((9, 5, 0x82, 0x0f, 0x42, 0x40, 1))
+
+        value, rest = decoder.decode(substrate)
+
+        assert tuple(value) == (1, 2, 1000000)
+        assert rest == b''
+
+    def testLargeBinaryRoundTrip(self):
+        substrate = encoder.encode(univ.Real((-1, 2, 76354972)))
+        value, rest = decoder.decode(substrate)
+
+        assert tuple(value) == (-1, 2, 76354972)
+        assert rest == b''
+
+
 class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase):
     def setUp(self):
         openType = opentype.OpenType(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/tests/type/test_tag.py 
new/pyasn1-0.6.4/tests/type/test_tag.py
--- old/pyasn1-0.6.3/tests/type/test_tag.py     2026-03-17 02:06:33.000000000 
+0100
+++ new/pyasn1-0.6.4/tests/type/test_tag.py     2026-07-09 03:12:14.000000000 
+0200
@@ -9,6 +9,7 @@
 
 from tests.base import BaseTestCase
 
+from pyasn1 import error
 from pyasn1.type import tag
 
 
@@ -23,6 +24,19 @@
     def testRepr(self):
         assert 'Tag' in repr(self.t1)
 
+    def testReprHugeTagId(self):
+        # must not hit the interpreter's int-to-str conversion limit
+        hugeTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1 << 
100000)
+        assert 'Tag' in repr(hugeTag)
+
+    def testNegativeHugeTagId(self):
+        try:
+            tag.Tag(tag.tagClassContext, tag.tagFormatSimple, -(1 << 100000))
+        except error.PyAsn1Error:
+            pass
+        else:
+            assert 0, 'negative tag ID tolerated'
+
 
 class TagCmpTestCase(TagTestCaseBase):
     def testCmp(self):
@@ -54,6 +68,12 @@
     def testRepr(self):
         assert 'TagSet' in repr(self.ts1)
 
+    def testReprHugeTagId(self):
+        # must not hit the interpreter's int-to-str conversion limit
+        hugeTagSet = self.ts1.tagImplicitly(
+            tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1 << 100000))
+        assert 'TagSet' in repr(hugeTagSet)
+
 
 class TagSetCmpTestCase(TagSetTestCaseBase):
     def testCmp(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyasn1-0.6.3/tests/type/test_univ.py 
new/pyasn1-0.6.4/tests/type/test_univ.py
--- old/pyasn1-0.6.3/tests/type/test_univ.py    2026-03-17 02:06:33.000000000 
+0100
+++ new/pyasn1-0.6.4/tests/type/test_univ.py    2026-07-09 03:12:14.000000000 
+0200
@@ -752,9 +752,49 @@
     def testFloat(self):
         assert float(univ.Real(4.0)) == 4.0, '__float__() fails'
 
+    def testFloatBase10Precision(self):
+        assert float(univ.Real((3, 10, 23))) == 3e23, '__float__() lost 
base-10 behavior'
+
+    def testFloatOverflow(self):
+        try:
+            float(univ.Real((1, 2, 1000000)))
+        except OverflowError:
+            pass
+        else:
+            assert 0, '__float__() tolerated overflow'
+
+        assert univ.Real((1, 2, 1000000)).prettyPrint() == '<overflow>'
+
+    def testFloatUnderflow(self):
+        assert float(univ.Real((1, 2, -1000000))) == 0.0, '__float__() failed 
underflow'
+
+    def testFloatZeroMantissa(self):
+        assert float(univ.Real((0, 10, 1000000000))) == 0.0, '__float__() 
failed zero mantissa'
+        assert float(univ.Real((0, 2, 1000000000))) == 0.0, '__float__() 
failed zero mantissa'
+
+    def testFloatBase10Overflow(self):
+        try:
+            float(univ.Real((1, 10, sys.float_info.max_10_exp + 1)))
+        except OverflowError:
+            pass
+        else:
+            assert 0, '__float__() tolerated base-10 overflow'
+
+    def testFloatBase10NormalizedOverflow(self):
+        try:
+            float(univ.Real((10, 10, sys.float_info.max_10_exp)))
+        except OverflowError:
+            pass
+        else:
+            assert 0, '__float__() tolerated normalized base-10 overflow'
+
     def testPrettyIn(self):
         assert univ.Real((3, 10, 0)) == 3, 'prettyIn() fails'
 
+    def testPrettyInBigBase10Mantissa(self):
+        assert tuple(univ.Real((10 ** 400, 10, 0))) == (1, 10, 400), \
+            'prettyIn() big mantissa normalization fails'
+
     # infinite float values
     def testStrInf(self):
         assert str(univ.Real('inf')) == 'inf', 'str() fails'

Reply via email to