https://github.com/python/cpython/commit/e2c403892400878707a20d4b7e183de505a64ca5
commit: e2c403892400878707a20d4b7e183de505a64ca5
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-02-10T12:21:35+02:00
summary:
gh-76763: Make chr() always raising ValueError for out-of-range values
(GH-114882)
Previously it raised OverflowError for very large or very small values.
files:
A Misc/NEWS.d/next/Core and
Builtins/2024-02-01-23-43-49.gh-issue-76763.o_2J6i.rst
M Lib/test/test_builtin.py
M Python/bltinmodule.c
M Python/clinic/bltinmodule.c.h
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 7a3ab2274a58f2..9a0bf524e3943f 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -308,14 +308,13 @@ class C3(C2): pass
self.assertTrue(callable(c3))
def test_chr(self):
+ self.assertEqual(chr(0), '\0')
self.assertEqual(chr(32), ' ')
self.assertEqual(chr(65), 'A')
self.assertEqual(chr(97), 'a')
self.assertEqual(chr(0xff), '\xff')
- self.assertRaises(ValueError, chr, 1<<24)
- self.assertEqual(chr(sys.maxunicode),
- str('\\U0010ffff'.encode("ascii"), 'unicode-escape'))
self.assertRaises(TypeError, chr)
+ self.assertRaises(TypeError, chr, 65.0)
self.assertEqual(chr(0x0000FFFF), "\U0000FFFF")
self.assertEqual(chr(0x00010000), "\U00010000")
self.assertEqual(chr(0x00010001), "\U00010001")
@@ -327,7 +326,11 @@ def test_chr(self):
self.assertEqual(chr(0x0010FFFF), "\U0010FFFF")
self.assertRaises(ValueError, chr, -1)
self.assertRaises(ValueError, chr, 0x00110000)
- self.assertRaises((OverflowError, ValueError), chr, 2**32)
+ self.assertRaises(ValueError, chr, 1<<24)
+ self.assertRaises(ValueError, chr, 2**32-1)
+ self.assertRaises(ValueError, chr, -2**32)
+ self.assertRaises(ValueError, chr, 2**1000)
+ self.assertRaises(ValueError, chr, -2**1000)
def test_cmp(self):
self.assertTrue(not hasattr(builtins, "cmp"))
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2024-02-01-23-43-49.gh-issue-76763.o_2J6i.rst b/Misc/NEWS.d/next/Core
and Builtins/2024-02-01-23-43-49.gh-issue-76763.o_2J6i.rst
new file mode 100644
index 00000000000000..d35d3d87073ddd
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2024-02-01-23-43-49.gh-issue-76763.o_2J6i.rst
@@ -0,0 +1,3 @@
+The :func:`chr` builtin function now always raises :exc:`ValueError` for
+values outside the valid range. Previously it raised :exc:`OverflowError` for
+very large or small values.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 31c1bf07e8fb91..b0074962b73799 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -703,17 +703,34 @@ builtin_format_impl(PyObject *module, PyObject *value,
PyObject *format_spec)
/*[clinic input]
chr as builtin_chr
- i: int
+ i: object
/
Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.
[clinic start generated code]*/
static PyObject *
-builtin_chr_impl(PyObject *module, int i)
-/*[clinic end generated code: output=c733afcd200afcb7 input=3f604ef45a70750d]*/
+builtin_chr(PyObject *module, PyObject *i)
+/*[clinic end generated code: output=d34f25b8035a9b10 input=f919867f0ba2f496]*/
{
- return PyUnicode_FromOrdinal(i);
+ int overflow;
+ long v = PyLong_AsLongAndOverflow(i, &overflow);
+ if (v == -1 && PyErr_Occurred()) {
+ return NULL;
+ }
+ if (overflow) {
+ v = overflow < 0 ? INT_MIN : INT_MAX;
+ /* Allow PyUnicode_FromOrdinal() to raise an exception */
+ }
+#if SIZEOF_INT < SIZEOF_LONG
+ else if (v < INT_MIN) {
+ v = INT_MIN;
+ }
+ else if (v > INT_MAX) {
+ v = INT_MAX;
+ }
+#endif
+ return PyUnicode_FromOrdinal(v);
}
diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h
index 8d40e659b54a57..3898f987cd61ea 100644
--- a/Python/clinic/bltinmodule.c.h
+++ b/Python/clinic/bltinmodule.c.h
@@ -233,25 +233,6 @@ PyDoc_STRVAR(builtin_chr__doc__,
#define BUILTIN_CHR_METHODDEF \
{"chr", (PyCFunction)builtin_chr, METH_O, builtin_chr__doc__},
-static PyObject *
-builtin_chr_impl(PyObject *module, int i);
-
-static PyObject *
-builtin_chr(PyObject *module, PyObject *arg)
-{
- PyObject *return_value = NULL;
- int i;
-
- i = PyLong_AsInt(arg);
- if (i == -1 && PyErr_Occurred()) {
- goto exit;
- }
- return_value = builtin_chr_impl(module, i);
-
-exit:
- return return_value;
-}
-
PyDoc_STRVAR(builtin_compile__doc__,
"compile($module, /, source, filename, mode, flags=0,\n"
" dont_inherit=False, optimize=-1, *, _feature_version=-1)\n"
@@ -1212,4 +1193,4 @@ builtin_issubclass(PyObject *module, PyObject *const
*args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=31bded5d08647a57 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=643a8d5f900e0c36 input=a9049054013a1b77]*/
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]