From e9ba3705de656215d52b8f8f4a2e7ad60190e944 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 3 Sep 2018 22:20:06 +0100 Subject: 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. --- Lib/test/test_math.py | 5 +++++ .../2018-03-19-00-59-20.bpo-33083.Htztjl.rst | 2 ++ Modules/mathmodule.c | 12 +++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-03-19-00-59-20.bpo-33083.Htztjl.rst diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index fff82fe..608789f 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -5,6 +5,7 @@ from test.support import run_unittest, verbose, requires_IEEE_754 from test import support import unittest import itertools +import decimal import math import os import platform @@ -510,6 +511,10 @@ class MathTests(unittest.TestCase): self.assertRaises(ValueError, math.factorial, -1e100) self.assertRaises(ValueError, math.factorial, math.pi) + def testFactorialNonIntegers(self): + self.assertRaises(TypeError, math.factorial, decimal.Decimal(5.2)) + self.assertRaises(TypeError, math.factorial, "5") + # Other implementations may place different upper bounds. @support.cpython_only def testFactorialHugeInputs(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-03-19-00-59-20.bpo-33083.Htztjl.rst b/Misc/NEWS.d/next/Core and Builtins/2018-03-19-00-59-20.bpo-33083.Htztjl.rst new file mode 100644 index 0000000..81df839 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-03-19-00-59-20.bpo-33083.Htztjl.rst @@ -0,0 +1,2 @@ +``math.factorial`` no longer accepts arguments that are not int-like. +Patch by Pablo Galindo. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 06a969c..e872e47 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -1656,7 +1656,7 @@ math_factorial(PyObject *module, PyObject *arg) { long x; int overflow; - PyObject *result, *odd_part, *two_valuation; + PyObject *result, *odd_part, *two_valuation, *pyint_form; if (PyFloat_Check(arg)) { PyObject *lx; @@ -1672,8 +1672,14 @@ math_factorial(PyObject *module, PyObject *arg) x = PyLong_AsLongAndOverflow(lx, &overflow); Py_DECREF(lx); } - else - x = PyLong_AsLongAndOverflow(arg, &overflow); + else { + pyint_form = PyNumber_Index(arg); + if (pyint_form == NULL) { + return NULL; + } + x = PyLong_AsLongAndOverflow(pyint_form, &overflow); + Py_DECREF(pyint_form); + } if (x == -1 && PyErr_Occurred()) { return NULL; -- cgit v0.12