diff --git a/meta/recipes-devtools/python/python-pyasn1.inc b/meta/recipes-devtools/python/python-pyasn1.inc index 96b4a3b52a..1780ee1d88 100644 --- a/meta/recipes-devtools/python/python-pyasn1.inc +++ b/meta/recipes-devtools/python/python-pyasn1.inc @@ -19,6 +19,7 @@ inherit ptest SRC_URI += " \ file://run-ptest \ file://CVE-2026-23490.patch \ + file://CVE-2026-59886.patch \ " RDEPENDS:${PN}-ptest += " \ diff --git a/meta/recipes-devtools/python/python3-pyasn1/CVE-2026-59886.patch b/meta/recipes-devtools/python/python3-pyasn1/CVE-2026-59886.patch new file mode 100644 index 0000000000..80468c6a5e --- /dev/null +++ b/meta/recipes-devtools/python/python3-pyasn1/CVE-2026-59886.patch @@ -0,0 +1,252 @@ +From 9b89b511a7284f17ef3a2de6d05fbf6030133abb Mon Sep 17 00:00:00 2001 +From: Simon Pichugin +Date: Wed, 8 Jul 2026 17:32:09 -0700 +Subject: [PATCH] Merge commit from fork + +CVE: CVE-2026-59886 +Upstream-Status: Backport [https://github.com/pyasn1/pyasn1/commit/e60c691cb91addb8fcefa2f537e85ede6fb1e886] + +(cherry picked from commit e60c691cb91addb8fcefa2f537e85ede6fb1e886) +Signed-off-by: Emily Vekariya +--- + pyasn1/type/univ.py | 21 +++++++++---- + tests/codec/ber/test_decoder.py | 53 +++++++++++++++++++++++++++------ + tests/codec/cer/test_decoder.py | 10 +++++++ + tests/codec/der/test_decoder.py | 19 ++++++++++++ + tests/type/test_univ.py | 40 +++++++++++++++++++++++++ + 5 files changed, 129 insertions(+), 14 deletions(-) + +diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py +index c5d0778..adff2df 100644 +--- a/pyasn1/type/univ.py ++++ b/pyasn1/type/univ.py +@@ -1318,7 +1318,7 @@ class Real(base.SimpleAsn1Type): + def __normalizeBase10(value): + m, b, e = value + while m and m % 10 == 0: +- m /= 10 ++ m //= 10 + e += 1 + return m, b, e + +@@ -1457,10 +1457,21 @@ class Real(base.SimpleAsn1Type): + 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 --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py +index f033dfd..f6ff7b0 100644 +--- a/tests/codec/ber/test_decoder.py ++++ b/tests/codec/ber/test_decoder.py +@@ -21,6 +21,7 @@ from pyasn1.type import univ + 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.compat.octets import ints2octs, str2octs, null + from pyasn1 import error +@@ -547,17 +548,51 @@ class RealDecoderTestCase(BaseTestCase): + ints2octs((9, 4, 161, 255, 1, 3)) + ) == (univ.Real((3, 2, -1020)), null) + +-# 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)) ++ ) + +-# def testBin6(self): +-# assert decoder.decode( +-# ints2octs((9, 5, 162, 0, 255, 255, 1)) +-# ) == (univ.Real((1, 2, 262140)), null) ++ 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 testLongFormBinaryRealExponentLength(self): ++ value, rest = decoder.decode( ++ bytes((9, 6, 0x83, 3, 0x0f, 0x42, 0x40, 1)) ++ ) + +-# def testBin7(self): +-# assert decoder.decode( +-# ints2octs((9, 7, 227, 4, 1, 35, 69, 103, 1)) +-# ) == (univ.Real((-1, 2, 76354972)), null) ++ 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() == '' ++ 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 --git a/tests/codec/cer/test_decoder.py b/tests/codec/cer/test_decoder.py +index 133affd..3d27194 100644 +--- a/tests/codec/cer/test_decoder.py ++++ b/tests/codec/cer/test_decoder.py +@@ -15,6 +15,7 @@ from pyasn1.type import opentype + from pyasn1.type import univ + from pyasn1.codec.cer import decoder + from pyasn1.compat.octets import ints2octs, str2octs, null ++from pyasn1.codec.cer import encoder + from pyasn1.error import PyAsn1Error + + +@@ -66,6 +67,15 @@ class OctetStringDecoderTestCase(BaseTestCase): + # TODO: test failures on short chunked and long unchunked substrate samples + + ++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 --git a/tests/codec/der/test_decoder.py b/tests/codec/der/test_decoder.py +index 5bc9deb..553563c 100644 +--- a/tests/codec/der/test_decoder.py ++++ b/tests/codec/der/test_decoder.py +@@ -15,6 +15,7 @@ from pyasn1.type import opentype + from pyasn1.type import univ + from pyasn1.codec.der import decoder + from pyasn1.compat.octets import ints2octs, null ++from pyasn1.codec.der import encoder + from pyasn1.error import PyAsn1Error + + +@@ -72,6 +73,24 @@ class OctetStringDecoderTestCase(BaseTestCase): + assert 0, 'chunked encoding 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 --git a/tests/type/test_univ.py b/tests/type/test_univ.py +index 8aec183..bc21c37 100644 +--- a/tests/type/test_univ.py ++++ b/tests/type/test_univ.py +@@ -780,9 +780,49 @@ class RealTestCase(BaseTestCase): + 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() == '' ++ ++ 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' +-- +2.34.1 +