Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c8c162e

Browse filesBrowse files
gh-106030: Miscellaneous fixes in Python/suggestions.c (GH-106031)
* PyDict_GetItem() and PyObject_HasAttr() suppress arbitrary errors and should not be used. * PyUnicode_CompareWithASCIIString() only works if the second argument is ASCII string. * Refleak in get_suggestions_for_name_error. * Use of borrowed pointer after possible freeing (self). * Add some missing error checks.
1 parent 9499b0f commit c8c162e
Copy full SHA for c8c162e

File tree

1 file changed

+27
-15
lines changed
Filter options

1 file changed

+27
-15
lines changed

‎Python/suggestions.c

Copy file name to clipboardExpand all lines: Python/suggestions.c
+27-15Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,15 @@ calculate_suggestions(PyObject *dir,
151151
}
152152
for (int i = 0; i < dir_size; ++i) {
153153
PyObject *item = PyList_GET_ITEM(dir, i);
154+
if (_PyUnicode_Equal(name, item)) {
155+
continue;
156+
}
154157
Py_ssize_t item_size;
155158
const char *item_str = PyUnicode_AsUTF8AndSize(item, &item_size);
156159
if (item_str == NULL) {
157160
PyMem_Free(buffer);
158161
return NULL;
159162
}
160-
if (PyUnicode_CompareWithASCIIString(name, item_str) == 0) {
161-
continue;
162-
}
163163
// No more than 1/3 of the involved characters should need changed.
164164
Py_ssize_t max_distance = (name_size + item_size + 3) * MOVE_COST / 6;
165165
// Don't take matches we've already beaten.
@@ -220,37 +220,48 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
220220
assert(code != NULL && code->co_localsplusnames != NULL);
221221

222222
PyObject *varnames = _PyCode_GetVarnames(code);
223+
Py_DECREF(code);
223224
if (varnames == NULL) {
224225
return NULL;
225226
}
226227
PyObject *dir = PySequence_List(varnames);
227228
Py_DECREF(varnames);
228-
Py_DECREF(code);
229229
if (dir == NULL) {
230230
return NULL;
231231
}
232232

233233
// Are we inside a method and the instance has an attribute called 'name'?
234-
if (PySequence_Contains(dir, &_Py_ID(self)) > 0) {
234+
int res = PySequence_Contains(dir, &_Py_ID(self));
235+
if (res < 0) {
236+
goto error;
237+
}
238+
if (res > 0) {
235239
PyObject* locals = PyFrame_GetLocals(frame);
236240
if (!locals) {
237241
goto error;
238242
}
239-
PyObject* self = PyDict_GetItem(locals, &_Py_ID(self)); /* borrowed */
240-
Py_DECREF(locals);
243+
PyObject* self = PyDict_GetItemWithError(locals, &_Py_ID(self)); /* borrowed */
241244
if (!self) {
245+
Py_DECREF(locals);
242246
goto error;
243247
}
244248

245-
if (PyObject_HasAttr(self, name)) {
249+
PyObject *value;
250+
res = _PyObject_LookupAttr(self, name, &value);
251+
Py_DECREF(locals);
252+
if (res < 0) {
253+
goto error;
254+
}
255+
if (value) {
256+
Py_DECREF(value);
246257
Py_DECREF(dir);
247-
return PyUnicode_FromFormat("self.%S", name);
258+
return PyUnicode_FromFormat("self.%U", name);
248259
}
249260
}
250261

251262
PyObject *suggestions = calculate_suggestions(dir, name);
252263
Py_DECREF(dir);
253-
if (suggestions != NULL) {
264+
if (suggestions != NULL || PyErr_Occurred()) {
254265
return suggestions;
255266
}
256267

@@ -260,7 +271,7 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
260271
}
261272
suggestions = calculate_suggestions(dir, name);
262273
Py_DECREF(dir);
263-
if (suggestions != NULL) {
274+
if (suggestions != NULL || PyErr_Occurred()) {
264275
return suggestions;
265276
}
266277

@@ -319,15 +330,16 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc)
319330
assert(frame != NULL);
320331

321332
PyObject* suggestion = get_suggestions_for_name_error(name, frame);
322-
bool is_stdlib_module = is_name_stdlib_module(name);
323-
324-
if (suggestion == NULL && !is_stdlib_module) {
333+
if (suggestion == NULL && PyErr_Occurred()) {
325334
return NULL;
326335
}
327336

328337
// Add a trailer ". Did you mean: (...)?"
329338
PyObject* result = NULL;
330-
if (!is_stdlib_module) {
339+
if (!is_name_stdlib_module(name)) {
340+
if (suggestion == NULL) {
341+
return NULL;
342+
}
331343
result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion);
332344
} else if (suggestion == NULL) {
333345
result = PyUnicode_FromFormat(". Did you forget to import %R?", name);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.