From 2f24f222bd4e8e9e630869cab4830b522e316df5 Mon Sep 17 00:00:00 2001 From: Michael Makukha Date: Mon, 23 Sep 2024 22:18:55 +0300 Subject: [PATCH 1/6] Add error handling for invalid sequence index --- Objects/stringlib/unicode_format.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h index 91c71ab5736c25..d70d30f640b4c1 100644 --- a/Objects/stringlib/unicode_format.h +++ b/Objects/stringlib/unicode_format.h @@ -462,8 +462,17 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs, tmp = getattr(obj, &name); else /* getitem lookup "[]" */ - if (index == -1) + if (index == -1) { + if (PySequence_Check(obj)) { + PyObject *str = SubString_new_object(&name); + /* TypeError is for backward compatibility */ + PyErr_Format(PyExc_TypeError, + "Sequence index must consist of digits, \"%S\" is not allowed", + str); + goto error; + } tmp = getitem_str(obj, &name); + } else if (PySequence_Check(obj)) tmp = getitem_sequence(obj, index); From 201e4b14287eb7bba2e2c6518766a646a4cd370a Mon Sep 17 00:00:00 2001 From: Michael Makukha Date: Tue, 24 Sep 2024 11:57:16 +0300 Subject: [PATCH 2/6] Add tests --- Lib/test/test_str.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index 6600dcf9157971..aa48cfbcccfd37 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -1388,6 +1388,10 @@ def __repr__(self): self.assertEqual("{!s}".format(n), 'N(data)') self.assertRaises(TypeError, "{}".format, n) + # String index for sequences + self.assertRaises(TypeError, "{[s]}".format, "abc") + self.assertRaises(TypeError, "{[-1]}".format, "abc") + def test_format_map(self): self.assertEqual(''.format_map({}), '') self.assertEqual('a'.format_map({}), 'a') From 0d678917e817cf10916dda930518444452fcca53 Mon Sep 17 00:00:00 2001 From: Michael Makukha Date: Tue, 24 Sep 2024 11:57:26 +0300 Subject: [PATCH 3/6] Add news entry --- .../2024-09-24-11-12-09.gh-issue-124294.jBPOm1.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2024-09-24-11-12-09.gh-issue-124294.jBPOm1.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-24-11-12-09.gh-issue-124294.jBPOm1.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-24-11-12-09.gh-issue-124294.jBPOm1.rst new file mode 100644 index 00000000000000..aa0839167fc08b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-24-11-12-09.gh-issue-124294.jBPOm1.rst @@ -0,0 +1,2 @@ +More informative error message in :func:`str.format` when passing negative +integer or string index to sequence. From 7ec5eb8015cefbd98334e0362852ee4c76ee682b Mon Sep 17 00:00:00 2001 From: Michael Makukha Date: Tue, 24 Sep 2024 11:58:12 +0300 Subject: [PATCH 4/6] Fix errors and update error message --- Objects/stringlib/unicode_format.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h index d70d30f640b4c1..0fa7c00cac24ea 100644 --- a/Objects/stringlib/unicode_format.h +++ b/Objects/stringlib/unicode_format.h @@ -464,11 +464,14 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs, /* getitem lookup "[]" */ if (index == -1) { if (PySequence_Check(obj)) { + /* string index can't be passed to sequence */ PyObject *str = SubString_new_object(&name); - /* TypeError is for backward compatibility */ - PyErr_Format(PyExc_TypeError, - "Sequence index must consist of digits, \"%S\" is not allowed", - str); + if (str != NULL) + PyErr_Format(PyExc_TypeError, + "Index must be a sequence of digits, string %R " + "is not allowed", + str); + Py_XDECREF(str); goto error; } tmp = getitem_str(obj, &name); From 080802acd443b4e3ecec8cbefaee4d1d7d10a156 Mon Sep 17 00:00:00 2001 From: Michael Makukha Date: Tue, 24 Sep 2024 17:22:26 +0300 Subject: [PATCH 5/6] Updatee tests --- Lib/test/test_str.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index aa48cfbcccfd37..e5a2b0faa9b3c0 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -1389,8 +1389,9 @@ def __repr__(self): self.assertRaises(TypeError, "{}".format, n) # String index for sequences - self.assertRaises(TypeError, "{[s]}".format, "abc") - self.assertRaises(TypeError, "{[-1]}".format, "abc") + index_msg = 'Index must be a sequence of digits' + self.assertRaisesRegex(TypeError, index_msg, "{[s]}".format, "abc") + self.assertRaisesRegex(TypeError, index_msg, "{[-1]}".format, "abc") def test_format_map(self): self.assertEqual(''.format_map({}), '') From 8eeca723216c196357fc718dfc091bac02f42588 Mon Sep 17 00:00:00 2001 From: Michael Makukha Date: Tue, 24 Sep 2024 17:29:28 +0300 Subject: [PATCH 6/6] PEP7-ize --- Objects/stringlib/unicode_format.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h index 0fa7c00cac24ea..10e1f4f2df52d6 100644 --- a/Objects/stringlib/unicode_format.h +++ b/Objects/stringlib/unicode_format.h @@ -466,11 +466,12 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs, if (PySequence_Check(obj)) { /* string index can't be passed to sequence */ PyObject *str = SubString_new_object(&name); - if (str != NULL) + if (str) { PyErr_Format(PyExc_TypeError, "Index must be a sequence of digits, string %R " "is not allowed", str); + } Py_XDECREF(str); goto error; }