From 85bcb1b26683f3f3def8858dd216539cadb1c308 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sat, 8 Mar 2025 22:13:50 -0300 Subject: [PATCH 1/5] Check that suggestion candidates in calculate_suggestions are strings. --- Python/suggestions.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Python/suggestions.c b/Python/suggestions.c index 2ce0bcfd54e23f..bb553ef9b3c909 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -148,6 +148,10 @@ _Py_CalculateSuggestions(PyObject *dir, } for (Py_ssize_t i = 0; i < dir_size; ++i) { PyObject *item = PyList_GET_ITEM(dir, i); + if (!PyUnicode_Check(item)) { + PyMem_Free(buffer); + return NULL; + } if (_PyUnicode_Equal(name, item)) { continue; } From 4586bbaef43b7dc8086a7e5648d40c355faad314 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sat, 8 Mar 2025 22:32:44 -0300 Subject: [PATCH 2/5] Add a test for the abort with non-string candidates in calculate_suggestions. --- Lib/test/test_traceback.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 68c4fa117a90f5..c33d9b27ae052b 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -4072,6 +4072,17 @@ class A: actual = self.get_suggestion(A(), 'bluch') self.assertNotIn("blech", actual) + def test_suggestions_do_not_trigger_with_non_string_candidates(self): + class Parent: + def __dir__(self): + return [0, 'blech'] + + class WithNonStringAttrs(Parent): + blech = None + + result = self.get_suggestion(WithNonStringAttrs(), "bluch") + self.assertNotIn("blech", result) + def test_getattr_suggestions_no_args(self): class A: blech = None From 22ac8be88459cc5c0c4f6afc3101ceb80c78a199 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sat, 8 Mar 2025 23:15:54 -0300 Subject: [PATCH 3/5] Use a test that actually aborts on 3.12, still not testing the code change in 3.14. --- Lib/test/test_traceback.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index c33d9b27ae052b..aae04a21443f1c 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -4073,15 +4073,12 @@ class A: self.assertNotIn("blech", actual) def test_suggestions_do_not_trigger_with_non_string_candidates(self): - class Parent: - def __dir__(self): - return [0, 'blech'] - - class WithNonStringAttrs(Parent): - blech = None + def run_module_code(): + import runpy + runpy._run_module_code("blech", {0: "", "bluch": ""}, "") - result = self.get_suggestion(WithNonStringAttrs(), "bluch") - self.assertNotIn("blech", result) + actual = self.get_exception(run_module_code, slice_start=-1, slice_end=None) + self.assertNotIn("bluch", actual[0]) def test_getattr_suggestions_no_args(self): class A: From b7022154626e94de839ea2073ec7d50135e78602 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Mon, 2 Jun 2025 09:31:50 -0300 Subject: [PATCH 4/5] Remove test added in baccfdb, add a new one. --- Lib/test/test_traceback.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 9a39db1b7cb19e..e0e904c1231ac3 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -4130,14 +4130,6 @@ class A: actual = self.get_suggestion(A(), 'bluch') self.assertNotIn("blech", actual) - def test_suggestions_do_not_trigger_with_non_string_candidates(self): - def run_module_code(): - import runpy - runpy._run_module_code("blech", {0: "", "bluch": ""}, "") - - actual = self.get_exception(run_module_code, slice_start=-1, slice_end=None) - self.assertNotIn("bluch", actual[0]) - def test_getattr_suggestions_no_args(self): class A: blech = None @@ -4748,6 +4740,13 @@ def test_suggestions_extension(self): None ) + self.assertRaises( + TypeError, + _suggestions._generate_suggestions, + ["hello", "world", 0, 1.1], + "hell", + ) + # gh-131936: _generate_suggestions() doesn't accept list subclasses class MyList(list): pass From 87b57945346e639e55e7e905fdd75c0325837744 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 12:37:00 +0000 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-06-02-12-36-52.gh-issue-129573.zY2VO9.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-12-36-52.gh-issue-129573.zY2VO9.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-12-36-52.gh-issue-129573.zY2VO9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-12-36-52.gh-issue-129573.zY2VO9.rst new file mode 100644 index 00000000000000..9290236ca32370 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-12-36-52.gh-issue-129573.zY2VO9.rst @@ -0,0 +1 @@ +Avoid possible abort when getting suggestions and there are non-string candidates.