Skip to content

Commit e9ba370

Browse files
authored
bpo-33083 - Make math.factorial reject arguments that are not int-like (GH-6149)
math.factorial() was accepting non-integral Decimal instances. This is inconsistent with the actual behaviour for floats, which are not accepted.
1 parent 65fc98e commit e9ba370

File tree

3 files changed

+16
-3
lines changed

3 files changed

+16
-3
lines changed

Lib/test/test_math.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from test import support
66
import unittest
77
import itertools
8+
import decimal
89
import math
910
import os
1011
import platform
@@ -510,6 +511,10 @@ def testFactorial(self):
510511
self.assertRaises(ValueError, math.factorial, -1e100)
511512
self.assertRaises(ValueError, math.factorial, math.pi)
512513

514+
def testFactorialNonIntegers(self):
515+
self.assertRaises(TypeError, math.factorial, decimal.Decimal(5.2))
516+
self.assertRaises(TypeError, math.factorial, "5")
517+
513518
# Other implementations may place different upper bounds.
514519
@support.cpython_only
515520
def testFactorialHugeInputs(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``math.factorial`` no longer accepts arguments that are not int-like.
2+
Patch by Pablo Galindo.

Modules/mathmodule.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ math_factorial(PyObject *module, PyObject *arg)
16561656
{
16571657
long x;
16581658
int overflow;
1659-
PyObject *result, *odd_part, *two_valuation;
1659+
PyObject *result, *odd_part, *two_valuation, *pyint_form;
16601660

16611661
if (PyFloat_Check(arg)) {
16621662
PyObject *lx;
@@ -1672,8 +1672,14 @@ math_factorial(PyObject *module, PyObject *arg)
16721672
x = PyLong_AsLongAndOverflow(lx, &overflow);
16731673
Py_DECREF(lx);
16741674
}
1675-
else
1676-
x = PyLong_AsLongAndOverflow(arg, &overflow);
1675+
else {
1676+
pyint_form = PyNumber_Index(arg);
1677+
if (pyint_form == NULL) {
1678+
return NULL;
1679+
}
1680+
x = PyLong_AsLongAndOverflow(pyint_form, &overflow);
1681+
Py_DECREF(pyint_form);
1682+
}
16771683

16781684
if (x == -1 && PyErr_Occurred()) {
16791685
return NULL;

0 commit comments

Comments
 (0)