8000 [3.12] gh-118164: str(10**10000) hangs if the C _decimal module is mi… · python/cpython@0c60524 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0c60524

Browse files
miss-islingtontim-oneserhiy-storchaka
authored
[3.12] gh-118164: str(10**10000) hangs if the C _decimal module is missing (GH-118503) (GH-118584)
Serhiy and I independently concluded that exact powers of 10 aren't possible in these contexts, so just checking the string length is sufficient. (cherry picked from commit 999f0c5) Co-authored-by: Tim Peters <tim.peters@gmail.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 53e8bdd commit 0c60524

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

Lib/_pydecimal.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,10 +2131,16 @@ def _power_exact(self, other, p):
21312131
else:
21322132
return None
21332133

2134-
if xc >= 10**p:
2134+
# An exact power of 10 is representable, but can convert to a
2135+
# string of any length. But an exact power of 10 shouldn't be
2136+
# possible at this point.
2137+
assert xc > 1, self
2138+
assert xc % 10 != 0, self
2139+
strxc = str(xc)
2140+
if len(strxc) > p:
21352141
return None
21362142
xe = -e-xe
2137-
return _dec_from_triple(0, str(xc), xe)
2143+
return _dec_from_triple(0, strxc, xe)
21382144

21392145
# now y is positive; find m and n such that y = m/n
21402146
if ye >= 0:
@@ -2184,13 +2190,18 @@ def _power_exact(self, other, p):
21842190
return None
21852191
xc = xc**m
21862192
xe *= m
2187-
if xc > 10**p:
2193+
# An exact power of 10 is representable, but can convert to a string
2194+
# of any length. But an exact power of 10 shouldn't be possible at
2195+
# this point.
2196+
assert xc > 1, self
2197+
assert xc % 10 != 0, self
2198+
str_xc = str(xc)
2199+
if len(str_xc) > p:
21882200
return None
21892201

21902202
# by this point the result *is* exactly representable
21912203
# adjust the exponent to get as close as possible to the ideal
21922204
# exponent, if necessary
2193-
str_xc = str(xc)
21942205
if other._isinteger() and other._sign == 0:
21952206
ideal_exponent = self._exp*int(other)
21962207
zeros = min(xe-ideal_exponent, p-len(str_xc))

Lib/test/test_decimal.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4722,9 +4722,33 @@ def test_py_exact_power(self):
47224722

47234723
c.prec = 1
47244724
x = Decimal("152587890625") ** Decimal('-0.5')
4725+
self.assertEqual(x, Decimal('3e-6'))
4726+
c.prec = 2
4727+
x = Decimal("152587890625") ** Decimal('-0.5')
4728+
self.assertEqual(x, Decimal('2.6e-6'))
4729+
c.prec = 3
4730+
x = Decimal("152587890625") ** Decimal('-0.5')
4731+
self.assertEqual(x, Decimal('2.56e-6'))
4732+
c.prec = 28
4733+
x = Decimal("152587890625") ** Decimal('-0.5')
4734+
self.assertEqual(x, Decimal('2.56e-6'))
4735+
47254736
c.prec = 201
47264737
x = Decimal(2**578) ** Decimal("-0.5")
47274738

4739+
# See https://github.com/python/cpython/issues/118027
4740+
# Testing for an exact power could appear to hang, in the Python
4741+
# version, as it attempted to compute 10**(MAX_EMAX + 1).
4742+
# Fixed via https://github.com/python/cpython/pull/118503.
4743+
c.prec = P.MAX_PREC
4744+
c.Emax = P.MAX_EMAX
4745+
c.Emin = P.MIN_EMIN
4746+
c.traps[P.Inexact] = 1
4747+
D2 = Decimal(2)
4748+
# If the bug is still present, the next statement won't complete.
4749+
res = D2 ** 117
4750+
self.assertEqual(res, 1 << 117)
4751+
47284752
def test_py_immutability_operations(self):
47294753
# Do operations and check that it didn't change internal objects.
47304754
Decimal = P.Decimal
@@ -5737,7 +5761,6 @@ def test_format_fallback_rounding(self):
57375761
with C.localcontext(rounding=C.ROUND_DOWN):
57385762
self.assertEqual(format(y, '#.1f'), '6.0')
57395763

5740-
57415764
@requires_docstrings
57425765
@requires_cdecimal
57435766
class SignatureTest(unittest.TestCase):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The Python implementation of the ``decimal`` module could appear to hang in relatively small power cases (like ``2**117``) if context precision was set to a very high value. A different method to check for exactly representable results is used now that doesn't rely on computing ``10**precision`` (which could be effectively too large to compute).

0 commit comments

Comments
 (0)
0